pax_global_header00006660000000000000000000000064142114117230014506gustar00rootroot0000000000000052 comment=7449df4de72e32ed861ae1503edba2b4d91b9a64 swtpm-0.6.3/000077500000000000000000000000001421141172300126665ustar00rootroot00000000000000swtpm-0.6.3/.github/000077500000000000000000000000001421141172300142265ustar00rootroot00000000000000swtpm-0.6.3/.github/ISSUE_TEMPLATE/000077500000000000000000000000001421141172300164115ustar00rootroot00000000000000swtpm-0.6.3/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000011051421141172300211000ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. 2. 3. 4. **Expected behavior** A clear and concise description of what you expected to happen. **Desktop (please complete the following information):** - OS: [e.g.Fedora] - Version [e.g. 33] **Versions of relevant components** - swtpm: - libtpms: - openssl: - gnutls: - ...: **Additional context** Add any other context about the problem here. swtpm-0.6.3/.gitignore000066400000000000000000000022021421141172300146520ustar00rootroot00000000000000*.egg-info *.exe *.exe.stackdump *.gcda *.gch *.gcno *.gcov *.la *.lo *.o *.patch *~ .deps .libs __pycache__ configure Makefile.in Makefile /aclocal.m4 /autom4te.cache /compile /config.guess /config.h /config.h.in /config.log /config.status /config.sub /depcomp /dist /install-sh /libtool /ltmain.sh /missing /stamp-h1 /swtpm-*.tar.gz /swtpm.spec /m4/* /.pc/* /etc/swtpm_setup.conf /patches/* /include/swtpm.h /man/man3/*.3 /man/man8/*.8 /samples/swtpm-create-user-config-files /samples/swtpm-localca /samples/swtpm-localca.conf /samples/swtpm_localca_conf.h /src/selinux/*.pp.bz2 /src/selinux/swtpm.pp /src/selinux/swtpm_svirt.fc /src/selinux/swtpm_svirt.if /src/selinux/swtpm_svirt.pp /src/selinux/swtpmcuse.pp /src/selinux/tmp /src/swtpm/swtpm /src/swtpm/swtpm_cuse /src/swtpm_bios/swtpm_bios /src/swtpm_cert/swtpm_cert /src/swtpm_ioctl/swtpm_ioctl src/swtpm_setup/swtpm_setup src/swtpm_setup/swtpm_setup_conf.h /test-driver tests/*.log tests/*.trs tests/test_config /debian/*debhelper* /debian/*substvars /debian/files /debian/swtpm /debian/swtpm-cuse /debian/swtpm-dev /debian/swtpm-libs /debian/swtpm-tools /debian/swtpm-tools.postinst /debian/tmp swtpm-0.6.3/.travis.yml000066400000000000000000000122131421141172300147760ustar00rootroot00000000000000env: global: - secure: mcAXlw5k/1yOP2RMKWEtvU2SnsuHo5Idoi5zZ+hLj2CzdvT77Wh8HWQ7NRsiamL+3dMPxzzy60IYNZQ8F29y3rvN7gASVsYn31G5UkmfvpPLiucuPADM1rNm8FYNlia0GFW4keP+LwMrBo6KDK9k0T8w4lquXBwMmNzhvCYVwkBIM5YwhXW5nk1dOJtf6zAb6gDH/VNEYTXXRKjA5Jvln7+EVHY61pEx6rJGa2GU0A49ms5UMJVzv85FraiHwlCPnNhQWGJ6sStqxsd5i6VBTCrkwMqnnA+ZBosqIJkBXp4OkudfPWE9vsn7TtuYdbheOkUIv6GRPFJNG3Vm3Wh/IwvSOILS5xAmsB3MxyK3BlILOYcsywiSzV5J4+s5Vnih4FaRQ3xx46Fq2ldatuk7npIxfdd3Co5V1KZh1pq3ckAdKlY2PEsQc0Kh72Lxf2N0XVw4s0H7gzrFk4/ghIvoCmAWBRSrN+R7wleEcmxDRgUZHP6Qc2ZNP+kljhBLqzinW2jyxPAqQS17g5Tb01+WfqkG/T5jboyIIe/OEQ5XbQp3/d8rUA8STpJxD25lwKKqlIqU3ZFWYfRT+pA0x83AdiTm53CJSQqFyCLtZCqK0XSZbLfmFzjZJ7I8FQxZoF2o03DDkL1Xs0z0sj87i3UnsYzxGdSrcU2JDK7qRIn39sM= sudo: required language: c dist: xenial addons: apt: packages: - automake - autoconf - libtool - libssl-dev - sed - make - gawk - sed - bash - dh-exec - python3-pip - python3-twisted - libfuse-dev - libglib2.0-dev - libjson-glib-dev - libgmp-dev - expect - libtasn1-dev - socat - findutils - gnutls-dev - gnutls-bin - libasan2 - softhsm2 - libseccomp-dev coverity_scan: project: name: swtpm description: Build submitted via Travis CI notification_email: stefanb@linux.vnet.ibm.com build_command_prepend: "git clone https://github.com/stefanberger/libtpms && cd libtpms && ./autogen.sh --with-openssl --prefix=/usr --with-tpm2 && make -j$(${NPROC:-nproc}) && sudo make install && cd .. && ./autogen.sh --with-openssl" build_command: make -j$(${NPROC:-nproc}) branch_pattern: coverity_scan before_install: - test $TRAVIS_BRANCH != coverity_scan -o ${TRAVIS_JOB_NUMBER##*.} = 1 || exit 0 - | # We need trousers only for the tss user if [ "$(uname -s)" = "Linux" ]; then sudo rm -rf /dev/tpm* # This is a work-around for Bionic where trousers otherwise fails to install sudo apt-get -y install trousers fi script: - sudo pip3 install --upgrade pip==20.3.3 - if [ ! -d libtpms ]; then git clone https://github.com/stefanberger/libtpms; fi - cd libtpms - if [ -n "${LIBTPMS_GIT_CHECKOUT}" ]; then git checkout "${LIBTPMS_GIT_CHECKOUT}" -b testing; fi - CFLAGS="${LIBTPMS_CFLAGS:--g -O2}" LDFLAGS="${LIBTPMS_LDFLAGS}" ./autogen.sh --with-openssl --prefix=${LIBTPMS_PREFIX:-/usr} --with-tpm2 ${LIBTPMS_CONFIG} && make -j$(${NPROC:-nproc}) && sudo make install - cd .. - ./autogen.sh ${CONFIG} && ${SUDO} make clean && export SWTPM_TEST_EXPENSIVE=${SWTPM_TEST_EXPENSIVE:-1} && export SWTPM_TEST_IBMTSS2=${SWTPM_TEST_IBMTSS2:-0} && export SWTPM_TEST_STORE_VOLATILE=${SWTPM_TEST_STORE_VOLATILE:-0} && ${SUDO} make -j$(${NPROC:-nproc}) ${CHECK} VERBOSE=1 - if [ -n "${RUN_TEST}" ]; then sudo make install && sudo ${PREFIX}/bin/swtpm_setup --tpmstate /tmp --create-ek-cert --create-platform-cert --tpm2 || { exit 1; }; fi after_failure: - for f in tests/*.log; do echo ">>>>>>> $f <<<<<<<"; cat $f; done matrix: include: - env: PREFIX="/usr" CONFIG="--with-openssl --prefix=${PREFIX}" CHECK="distcheck" RUN_TEST="1" - dist: bionic env: PREFIX="/usr" CONFIG="--with-openssl --prefix=/usr --enable-test-coverage" SUDO="sudo" CHECK="check" SWTPM_TEST_IBMTSS2="1" SWTPM_TEST_STORE_VOLATILE="1" before_script: - sudo apt-get -y install tss2 - sudo pip install cpp-coveralls - p=$PWD; while [ "$PWD" != "/" ]; do chmod o+x . &>/dev/null ; cd .. ; done; cd $p && sudo mkdir src/swtpm/.libs && sudo chown nobody src/swtpm src/swtpm/.libs after_success: - uidgid="$(id -nu):$(id -ng)" && sudo chown -R ${uidgid} ./ && cpp-coveralls --gcov-options '\-lp' -e libtpms - env: CFLAGS="-fsanitize=address -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBTPMS_CFLAGS="-fsanitize=address -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBS="-lasan" ASAN_OPTIONS="halt_on_error=1" PREFIX="/usr" CONFIG="--with-openssl --prefix=${PREFIX} --without-seccomp" SUDO="sudo" CHECK="check" - env: CFLAGS="-fsanitize=address -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBTPMS_CFLAGS="-fsanitize=address -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBTPMS_CONFIG="--disable-use-openssl-functions" LIBS="-lasan" ASAN_OPTIONS="halt_on_error=1" PREFIX="/usr" CONFIG="--with-openssl --prefix=${PREFIX} --without-seccomp" SUDO="sudo" CHECK="check" - env: CFLAGS="-fsanitize=undefined -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBTPMS_CFLAGS="-fsanitize=undefined -g -fno-omit-frame-pointer -fno-sanitize-recover" LIBS="-lubsan" UBSAN_OPTIONS="halt_on_error=1" PREFIX="/usr" CONFIG="--with-openssl --prefix=${PREFIX}" SUDO="sudo" CHECK="check" swtpm-0.6.3/CHANGES000066400000000000000000000125721421141172300136700ustar00rootroot00000000000000CHANGES - changes for swtpm version 0.6.3: - swtpm: - Do not chdir(/) when using --daemon - swtpm-localca: - Re-implement variable resolution for swtpm-localca.conf - tests: - Use ${WORKDIR} in config files to test env. var replacement - man: - Add missing .config directory to path description when using ${HOME} - build-sys: - Add probing for -fstack-protector - configure: Fix typo TPM2 -> TMP2 version 0.6.2: - swtpm: - Check header size indicator against expected size (CVE-2022-23645) - swtpm-localca: - Test for available issuercert before creating CA - swtpm_setup: - Report stderr as returned by external tool (swtpm-localcal) - Fix exit code on error to be '1'. version 0.6.1: - swtpm: - Clear keys from stack and heap - swtpm-localca: - Add missing else branch for pkcs11 and PIN - swtpm_setup: - Initialize Gerror and free it - Replace '\\s' in regex with [[:space:]] to fix cygwin - tests: - Kill tpm2-abrmd with SIGKILL rather SIGTERM - build-sys: - Use -DOPENSSL_SUPPRESS_DEPRECATED to suppress deprecation warnings (OSSL 3) - Enable configuring with CFLAGS and passing additional CFLAGS on build version 0.6.0: - swtpm: - Fix --print-capabilities for 'swtpm chardev' - Various cleanups and fixes (coverity) - Addressed potential symlink attack issue (CVE-2020-28407) - swtpm_setup: - Rewritten in 'C'; needs json-glib - Addressed potential symlink attack issue (CVE-2020-28407) - swtpm_ioctl: - Use timeouts for communicating with swtpm (Unix socket) - swtpm-localca: - Rewritten in 'C' - tests: - Use the IBM TSS2 v1.6.0's test suite - Store and also restore the volatile state at every step when running IBM TSS2 test suite - Various cleanup - build-sys: - Add HARDENING_CFLAGS and _LDFLAGS to all C programs version 0.5.0: - swtpm: - Write files atomically using a temp file and then renaming - swtpm_setup: - Removed remaining 'c' wrapper program - Do not truncate logfile when testing write-access (regression) - Remove TPM state file in case error occurred - swtpm-localca: - Rewrite in python - Allow passing pkcs11 PIN using signingkey_password - Allow passing environment variables needed for pkcs11 modules using swtpm-localca.conf and format 'env:VARNAME=VALUE'. - build-sys: - Add python-install and python-uninstall targets - Add configure option to disable installation of Python module - Use -Wl,-z,relro and -Wl,-z,now only when linking (clang) - Use AC_LINK_IFELSE to check whether support for hardening flags version 0.4.0: - swtpm: - Invoke print capabilities after choosing TPM version - Add some recent syscalls to seccomp blacklist - swtpm_cert: - Support --ecc-curveid option to pass curve id - swtpm_setup & related scripts: - Rewrite swtpm_setup.sh in python with TPM 1.2 not requiring tcsd and TPM tools anymore; new dependencies: - python3: pip, cryptography, setuptools dropped dependencies for swtpm_setup: - tcsd, expect, tpm-tools (some still needed for pkcs11 tests) - Added support for RSA 3072 keys (for libtpms-0.8.0) and moved to ECC NIST P384 curve; default RSA key size is still 2048 - Added support for --rsa-keysize option - Extend script to create a CA using a TPM 2 for signing - tests: - Use the IBM TSS2 v1.5.0's test suite - Add test case for loading of an NVRAM completely full with keys - Have softhsm_setup use temporary directory for softhsm config & state - various other improvements - man pages: - Improvements - build-sys: - clang: properly test for linker flag 'now' and 'relro' - Gentoo: explicitly link libswtpm_libtpms with -lcrypto - Ownership of /var/lib/swtpm-localca is now tss:root and mode flags 0750. version 0.3.0: - swtpm: - Support for applying 'TPM Startup' command during initialization - Use writev_full rather than writev; fixes --vtpm-proxy EIO error - Only accept() new client ctrl connection if we have none (bugfix) - swtpm_setup & related scripts: - Support whitespaces in filenames and paths - Do not fail on future PCR banks' hashes - swtpm_cert: - Fix OIDs for TPM 2 platforms data - Option parsing cleanup - Support for passing password in various forms - Use gnutls_x509_crt_get_subject_key_id API call for subj keyId - Support 64bit serial numbers read from command line - swtpm_ioctl: - Block SIGPIPE so we can get EPIPE on write() - swtpm_bios: - Block SIGPIPE so we can get EPIPE on write() - tests: - Increased timeouts and better support for running tests with executables run by valgrind - Allow running tests with choice of seccomp profile option (SWTPM_TEST_SECCOMP_OPT) to enable building for Ubuntu - Various cleanups & fixes - SELinux: - More rules added for support on F30 version 0.2.0: - Linux: swtpm now runs with a seccomp profile (blacklist) if compiled with libseccomp support - Added subpport for passing key and passphrase via file descriptor - TPM 2 commands can now be prefixed by 'the TCG header' and responses will have a 4-byte prefix and 4-byte suffix. - Added --print-capabilities command line option - Proper handling on EINTR on read, poll, and write version 0.1.0: first public release swtpm-0.6.3/COPYING000066400000000000000000000001001421141172300137100ustar00rootroot00000000000000See the LICENSE file for the license applicable to this project.swtpm-0.6.3/DCO1.1.txt000066400000000000000000000023601421141172300142550ustar00rootroot00000000000000Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. swtpm-0.6.3/INSTALL000066400000000000000000000022731421141172300137230ustar00rootroot00000000000000Building and running the swtpm has dependencies on the following packages: - automake - autoconf - bash - coreutils - expect - libtool - sed - libtpms - libtpms-devel - fuse - fuse-devel - glib2 - glib2-devel - net-tools - python3 - python3-twisted - selinux-policy-devel - trousers - tpm-tools - gnutls - gnutls-devel - libtasn1 - libtasn1-tools - libtasn1-devel - rpm-build (to build RPMs) Debian/Ubuntu also needs the following packages to build: - build-essential - devscripts - equivs On RHEL or Fedora use either one of the following methods to install the above dependencies: - sudo dnf builddep ./dist/swtpm.spec (Fedora >= 22) - sudo yum install yum-utils ; sudo yum-builddep ./dist/swtpm.spec (RHEL and Fedora <= 21) - sudo yum install On Ubuntu use the following command: - sudo mk-build-deps --install ./debian/control Use the following sequence to build and install the Software TPM. ./autogen.sh --prefix=/usr make make check make install To build an rpm on a Fedora or RHEL host do: ./autogen.sh make dist rpmbuild -ta swtpm-*.tar.gz To build a Debian package on a Debian compatible host do: echo "libtpms0 libtpms" > ./debian/shlibs.local debuild -us -uc swtpm-0.6.3/LICENSE000066400000000000000000000030001421141172300136640ustar00rootroot00000000000000SWTPM license ------------- 3-clause BSD license (c) Copyright IBM Corporation 2006, 2010. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the names of the IBM Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. swtpm-0.6.3/Makefile.am000066400000000000000000000006411421141172300147230ustar00rootroot00000000000000# # Makefile.am # # For the license, see the COPYING file in the root directory. # SUBDIRS = \ etc \ include \ man \ samples \ src \ tests ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ CHANGES \ INSTALL \ LICENSE \ COPYING \ README \ swtpm.spec \ autogen.sh if WITH_SELINUX selinux-install selinux-uninstall: @cd src/selinux && $(MAKE) $(AM_MAKEFLAGS) $@ endif .PHONY: selinux-install selinux-uninstall swtpm-0.6.3/README000066400000000000000000000013161421141172300135470ustar00rootroot00000000000000SWTPM - Software TPM Emulator David Safford safford@us.ibm.com Stefan Berger stefanb@us.ibm.com The SWTPM package provides TPM emulators with different front-end interfaces to libtpms. TPM emulators provide socket interfaces (TCP/IP and Unix) and the Linux CUSE interface for the creation of multiple native /dev/vtpm* devices. The SWTPM package also provides several tools for using the TPM emulator, creating certificates for a TPM, and simulating the manufacturing of a TPM by creating a TPM's EK and platform certificates etc. Please read the READMEs in the individual tool's directory under src/. Please consult the Wiki for information about swtpm: https://github.com/stefanberger/swtpm/wiki swtpm-0.6.3/TODO000066400000000000000000000016041421141172300133570ustar00rootroot00000000000000Future capabilities needed -------------------------- - flag indicating that cancellation of commands is supported - patches for cancellation of key creation exists - improve on the logging - extend --ctrl (control) interface with more capabilities supported with the ioctls in the CUSE TPM swtpm_cert: - support for AIK Certs; takes EK and Platform certs as input: - copy data from EK Cert : 3.5.9 .11 - copy data from Platform Cert: 3.5.9, .11 - needs implementation of some more TPM specific X.509 attributes that encode the data in ASN.1; - Unified cert specs 3.5.9, 3.5.11, 3.5.22, 3.5.23. 3.5.24, 3.5.25, 3.5.26, 3.5.27 Status on RHEL 7.2: - the following bug is problematic for FreeBL usage: https://bugzilla.redhat.com/show_bug.cgi?id=1249720 - the following bug is problematic for swtpm_setup : https://bugzilla.redhat.com/show_bug.cgi?id=1126097 swtpm-0.6.3/autogen.sh000077500000000000000000000004051421141172300146660ustar00rootroot00000000000000#!/bin/sh set -e # exit on errors srcdir=`dirname $0` test -z "$srcdir" && srcdir=. olddir=`pwd` cd "$srcdir" test ! -d m4 && mkdir m4 autoreconf --verbose --force --install cd "$olddir" if [ -z "$NOCONFIGURE" ]; then "$srcdir"/configure ${1+"$@"} fi swtpm-0.6.3/configure.ac000066400000000000000000000424541421141172300151650ustar00rootroot00000000000000# # configure.ac # # The Initial Developer of the Original Code is International # Business Machines Corporation. Portions created by IBM # Corporation are Copyright (C) 2014 International Business # Machines Corporation. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the Common Public License as published by # IBM Corporation; either version 1 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # Common Public License for more details. # # You should have received a copy of the Common Public License # along with this program; if not, a copy can be viewed at # http://www.opensource.org/licenses/cpl1.0.php. # # This file is derived from tpm-tool's configure.in. # AC_INIT([swtpm], [0.6.3]) AC_PREREQ([2.69]) AC_CONFIG_SRCDIR(Makefile.am) AC_CONFIG_HEADERS([config.h]) SWTPM_VER_MAJOR=`echo $PACKAGE_VERSION | cut -d "." -f1` SWTPM_VER_MINOR=`echo $PACKAGE_VERSION | cut -d "." -f2` SWTPM_VER_MICRO=`echo $PACKAGE_VERSION | cut -d "." -f3` AC_SUBST([SWTPM_VER_MAJOR]) AC_SUBST([SWTPM_VER_MINOR]) AC_SUBST([SWTPM_VER_MICRO]) dnl Check for programs AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S LT_INIT AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AC_CANONICAL_HOST AM_INIT_AUTOMAKE([foreign 1.6]) AM_SILENT_RULES([yes]) DEBUG="" AC_MSG_CHECKING([for debug-enabled build]) AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[create a debug build]), [if test "$enableval" = "yes"; then DEBUG="yes" AC_MSG_RESULT([yes]) else DEBUG="no" AC_MSG_RESULT([no]) fi], [DEBUG="no", AC_MSG_RESULT([no])]) # If the user has not set CFLAGS, do something appropriate test_CFLAGS=${CFLAGS+set} if test "$test_CFLAGS" != set; then if test "$DEBUG" = "yes"; then CFLAGS="-O0 -g -DDEBUG" else CFLAGS="-g -O2" fi elif test "$DEBUG" = "yes"; then CFLAGS="$CFLAGS -O0 -g -DDEBUG" fi AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_PROG_CC AC_PROG_INSTALL AC_PROG_MKDIR_P AC_ARG_WITH([selinux], AS_HELP_STRING([--with-selinux], [add SELinux policy extensions @<:@default=check@:>@])) m4_divert_text([DEFAULTS], [with_selinux=check]) dnl Check for SELinux policy support if test "$with_selinux" != "no"; then if test "$with_selinux" = "check" || test "$with_selinux" = "yes"; then if ! test -f /usr/share/selinux/devel/Makefile; then if test "$with_selinux" = "yes"; then AC_MSG_ERROR("Is selinux-policy-devel installed?") else with_selinux="no" fi fi AC_PATH_PROG([SEMODULE], semodule) if test "x$SEMODULE" = "x"; then if test "$with_selinux" = "yes"; then AC_MSG_ERROR("Is selinux-policy-devel installed?") else with_selinux="no" fi fi if test "$with_selinux" = "check"; then with_selinux="yes" fi fi fi AM_CONDITIONAL([WITH_SELINUX], [test "x$with_selinux" = "xyes"]) if test "$prefix" = "/usr" && test "$sysconfdir" = '${prefix}/etc'; then sysconfdir="/etc" fi if test "$prefix" = "" && test "$datarootdir" = '${prefix}/share'; then datarootdir="/usr/share" fi if test "$prefix" = "/usr" && test "$localstatedir" = '${prefix}/var'; then localstatedir="/var" fi if test "x$prefix" = "xNONE"; then prefix="/usr/local" fi SYSCONFDIR=`eval echo $sysconfdir` DATAROOTDIR=`eval echo $datarootdir` LOCALSTATEDIR=`eval echo $localstatedir` AC_SUBST([SYSCONFDIR]) AC_SUBST([DATAROOTDIR]) AC_SUBST([LOCALSTATEDIR]) cryptolib=openssl AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl], [build with openssl library])], [], []) case "$cryptolib" in openssl) AC_CHECK_LIB(crypto, [AES_set_encrypt_key], [true], AC_MSG_ERROR(Faulty openssl crypto library)) AC_CHECK_HEADERS([openssl/aes.h],[], AC_MSG_ERROR(Is openssl-devel/libssl-dev installed?)) AC_MSG_RESULT([Building with openssl crypto library]) LIBCRYPTO_LIBS=$(pkg-config --libs libcrypto) AC_SUBST([LIBCRYPTO_LIBS]) LIBCRYPTO_EXTRA_CFLAGS="-DOPENSSL_SUPPRESS_DEPRECATED" AC_SUBST([LIBCRYPTO_EXTRA_CFLAGS]) ;; esac LIBTASN1_LIBS=$(pkg-config --libs libtasn1) if test $? -ne 0; then AC_MSG_ERROR("Is libtasn1-devel installed? -- could not get libs for libtasn1") fi AC_SUBST([LIBTASN1_LIBS]) PKG_CHECK_MODULES( [LIBTPMS], [libtpms], , AC_MSG_ERROR("no libtpms.pc found; please set PKG_CONFIG_PATH to the directory where libtpms.pc is located") ) LDFLAGS="$LDFLAGS $LIBTPMS_LIBS" CFLAGS="$CFLAGS $LIBTPMS_CFLAGS" AC_CHECK_LIB(tpms, TPMLIB_ChooseTPMVersion,[true], AC_MSG_ERROR("libtpms 0.6 or later is required") ) AC_SUBST([LIBTPMS_LIBS]) AC_CHECK_LIB(c, clock_gettime, LIBRT_LIBS="", LIBRT_LIBS="-lrt") AC_SUBST([LIBRT_LIBS]) AC_PATH_PROG([TCSD], tcsd) if test "x$TCSD" = "x"; then have_tcsd=no AC_MSG_WARN([tcsd could not be found; typically need it for tss user account and tests]) else have_tcsd=yes fi AM_CONDITIONAL([HAVE_TCSD], test "$have_tcsd" != "no") dnl We either need netstat (more common across systems) or 'ss' for test cases AC_PATH_PROG([NETSTAT], [netstat]) if test "x$NETSTAT" = "x"; then AC_PATH_PROG([SS], [ss]) if test "x$SS" = "x"; then AC_MSG_ERROR(['netstat' and 'ss' tools are missing for tests: net-tools OR iproute/iproute2 package]) fi fi AC_MSG_CHECKING([for whether to build with CUSE interface]) AC_ARG_WITH([cuse], AS_HELP_STRING([--with-cuse],[build with CUSE interface]), [], [with_cuse=check] ) if test "$with_cuse" != "no"; then LIBFUSE_CFLAGS=$(pkg-config fuse --cflags 2>/dev/null) if test $? -ne 0; then if test "$with_cuse" = "yes"; then AC_MSG_ERROR("Is fuse-devel installed? -- could not get cflags for libfuse") else with_cuse=no fi else with_cuse=yes fi fi JSON_GLIB_CFLAGS=$(pkg-config --cflags json-glib-1.0) if test $? -ne 0; then AC_MSG_ERROR("Is libjson-glib-dev/json-glib-devel installed? -- could not get cflags") fi AC_SUBST([JSON_GLIB_CFLAGS]) JSON_GLIB_LIBS=$(pkg-config --libs json-glib-1.0) if test $? -ne 0; then AC_MSG_ERROR("Is libjson-glib-dev/json-glib-devel installed? -- could not get libs") fi AC_SUBST([JSON_GLIB_LIBS]) GLIB_CFLAGS=$(pkg-config --cflags glib-2.0) if test $? -ne 0; then AC_MSG_ERROR("Is libglib-2.0-dev/glib2-devel installed? -- could not get cflags") fi AC_SUBST([GLIB_CFLAGS]) GLIB_LIBS=$(pkg-config --libs glib-2.0) if test $? -ne 0; then AC_MSG_ERROR("Is libglib-2.0-dev/glib2-devel installed? -- could not get cflags") fi AC_SUBST([GLIB_LIBS]) dnl with_cuse is now yes or no if test "$with_cuse" != "no"; then LIBFUSE_LIBS=$(pkg-config fuse --libs) if test $? -ne 0; then AC_MSG_ERROR("Is fuse-devel installed? -- could not get libs for libfuse") fi AC_SUBST([LIBFUSE_CFLAGS]) AC_SUBST([LIBFUSE_LIBS]) AC_DEFINE_UNQUOTED([WITH_CUSE], 1, [whether to build with CUSE interface]) GTHREAD_LIBS=$(pkg-config --libs gthread-2.0) if test $? -ne 0; then AC_MSG_ERROR("Is glib-2.0 installed? -- could not get libs for gthread-2.0") fi AC_SUBST([GTHREAD_LIBS]) fi AM_CONDITIONAL([WITH_CUSE],[test "$with_cuse" = "yes"]) AC_MSG_RESULT($with_cuse) AC_MSG_CHECKING([for whether to build with chardev interface]) case $host_os in linux-*) with_chardev=yes AC_DEFINE_UNQUOTED([WITH_CHARDEV], 1, [whether to build with chardev interface]) ;; *) with_chardev=no esac AM_CONDITIONAL([WITH_CHARDEV],[test "$with_chardev" = "yes"]) AC_MSG_RESULT($with_cuse) AC_ARG_WITH([gnutls], AS_HELP_STRING([--with-gnutls],[build with gnutls library]), [], [with_gnutls=check] ) if test "x$with_gnutls" != "xno"; then GNUTLS_LDFLAGS=$(pkg-config --libs gnutls) if test $? -ne 0; then if test "x$with_gnutls" = "xyes"; then AC_MSG_ERROR("Is gnutls installed? -- could not get libs for gnutls") else with_gnutls=no fi fi fi if test "x$with_gnutls" != "xno"; then AC_PATH_PROG([GNUTLS_CERTTOOL], certtool) if test "x$GNUTLS_CERTTOOL" = "x"; then if test "x$with_gnutls" = "xyes"; then AC_MSG_ERROR("Could not find certtool. Is gnutls-utils/gnutls-bin installed?") else with_gnutls=no fi fi dnl certtool changed how it takes private key passwords dnl 3.3.29 is too old (RHEL 7); we need at least gnutls 3.4.0 AC_MSG_CHECKING([for gnutls 3.4.0 or later]) $(pkg-config gnutls --atleast-version=3.4.0) if test $? -ne 0; then AC_MSG_ERROR([gnutls 3.4.0 is required]) fi AC_MSG_RESULT([yes]) fi if test "x$with_gnutls" != "xno"; then ORIG_CFLAGS="$CFLAGS" GNUTLS_CFLAGS=$(pkg-config gnutls --cflags) CFLAGS="$CFLAGS $GNUTLS_CFLAGS $GNUTLS_LDFLAGS" AC_CHECK_LIB([gnutls], [gnutls_load_file], [ GNUTLS_LIBS=-lgnutls ], [if test "x$with_gnutls" = "xyes"; then AC_MSG_ERROR([GNUTLS >= 3.1.0 library not found: libgnutls.so]) else with_gnutls="no" fi]) CFLAGS="$ORIG_CFLAGS" fi if test "x$with_gnutls" != "xno"; then ORIG_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $GNUTLS_CFLAGS" AC_CHECK_HEADER(gnutls/abstract.h, [], \ [if test "x$with_gnutls" = "xyes"; then AC_MSG_ERROR([GNUTLS >= 3.1.0 library header not found: gnutls/abstract.h]) else with_gnutls="no" fi]) CFLAGS="$ORIG_CFLAGS" fi if test "x$with_gnutls" != "xno"; then with_gnutls="yes" fi AM_CONDITIONAL([WITH_GNUTLS], [test "x$with_gnutls" = "xyes"]) AC_SUBST([GNUTLS_LIBS]) AC_PATH_PROG([EXPECT], expect) if test "x$EXPECT" = "x"; then AC_MSG_ERROR([expect is required: expect package]) fi AC_PATH_PROG([GAWK], gawk) if test "x$GAWK" = "x"; then AC_MSG_ERROR([gawk is required: gawk package]) fi AC_PATH_PROG([SOCAT], socat) if test "x$SOCAT" = "x"; then AC_MSG_ERROR([socat is required: socat package]) fi AC_PATH_PROG([BASE64], base64) if test "x$BASE64" = "x"; then AC_MSG_ERROR([base64 is required: base64 package]) fi AC_PATH_PROG([CP], cp) if test "x$CP" = "x"; then AC_MSG_ERROR([cp is required]) fi AM_PATH_PYTHON([3.3]) AC_PATH_PROG([PIP3], pip3) if test "x$PIP3" = "x"; then AC_PATH_PROG([PIP3], pip) if test "x$PIP3" = "x"; then AC_MSG_WARN([pip3 is required to uninstall the built package]) else AC_MSG_WARN([Using pip as pip3 tool]) fi fi AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [Disable hardening flags])) if test "x$enable_hardening" != "xno"; then # Some versions of gcc fail with -Wstack-protector, # some with -Wstack-protector-strong enabled if ! $CC -fstack-protector-strong -Wstack-protector $srcdir/include/swtpm/tpm_ioctl.h 2>/dev/null; then if $CC -fstack-protector -Wstack-protector $srcdir/include/swtpm/tpm_ioctl.h 2>/dev/null; then HARDENING_CFLAGS="-fstack-protector -Wstack-protector" fi else HARDENING_CFLAGS="-fstack-protector-strong -Wstack-protector" fi dnl Must not have -O0 but must have a -O for -D_FORTIFY_SOURCE=2 TMP1="$(echo $CFLAGS | sed -n 's/.*\(-O0\).*/\1/p')" TMP2="$(echo $CFLAGS | sed -n 's/.*\(-O\).*/\1/p')" if test -z "$TMP1" && test -n "$TMP2"; then HARDENING_CFLAGS="$HARDENING_CFLAGS -D_FORTIFY_SOURCE=2 " fi dnl Check linker for 'relro' and 'now' save_CFLAGS="$CFLAGS" CFLAGS="-Wl,-z,relro -Werror" AC_MSG_CHECKING([whether linker supports -Wl,-z,relro]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[int main() { return 0; }]])], [HARDENING_LDFLAGS="$HARDENING_LDFLAGS -Wl,-z,relro" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)] ) CFLAGS="-Wl,-z,now -Werror" AC_MSG_CHECKING([whether linker supports -Wl,-z,now]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[int main() { return 0; }]])], [HARDENING_LDFLAGS="$HARDENING_LDFLAGS -Wl,-z,now" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)] ) CFLAGS="$save_CFLAGS" AC_SUBST([HARDENING_CFLAGS]) AC_SUBST([HARDENING_LDFLAGS]) fi AC_ARG_ENABLE([test-coverage], AS_HELP_STRING([--enable-test-coverage], [Enable test coverage flags])) if test "x$enable_test_coverage" = "xyes"; then COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage" COVERAGE_LDFLAGS="-fprofile-arcs" fi AC_ARG_WITH([tss-user], AS_HELP_STRING([--with-tss-user=TSS_USER],[The tss user to use]), [TSS_USER="$withval"], [TSS_USER="tss"] ) AC_ARG_WITH([tss-group], AS_HELP_STRING([--with-tss-group=TSS_GROUP],[The tss group to use]), [TSS_GROUP="$withval"], [TSS_GROUP="tss"] ) case $have_tcsd in yes) AC_MSG_CHECKING([whether TSS_USER $TSS_USER is available]) if ! test $(id -u $TSS_USER); then AC_MSG_ERROR(["$TSS_USER is not available"]) else AC_MSG_RESULT([yes]) fi AC_MSG_CHECKING([whether TSS_GROUP $TSS_GROUP is available]) if ! test $(id -g $TSS_GROUP); then AC_MSG_ERROR(["$TSS_GROUP is not available"]) else AC_MSG_RESULT([yes]) fi ;; esac AC_SUBST([TSS_USER]) AC_SUBST([TSS_GROUP]) CFLAGS="$CFLAGS -Wreturn-type -Wsign-compare -Wswitch-enum" CFLAGS="$CFLAGS -Wmissing-prototypes -Wall -Werror" CFLAGS="$CFLAGS -Wformat -Wformat-security" CFLAGS="$CFLAGS $GNUTLS_CFLAGS $COVERAGE_CFLAGS" LDFLAGS="$LDFLAGS $COVERAGE_LDFLAGS" dnl Simulate the following for systems with pkg-config < 0.28: dnl PKG_CHECK_VAR([libtpms_cryptolib], [libtpms], [cryptolib], dnl [], AC_MSG_ERROR([Could not determine libtpms crypto library.])) PKG_PROG_PKG_CONFIG AC_MSG_CHECKING([Checking the crypto library libtpms is linked to]) libtpms_cryptolib=`$PKG_CONFIG --variable cryptolib libtpms` if test "x$libtpms_cryptolib" = "x"; then AC_MSG_WARN([Could not determine the crypto library libtpms is using, assuming ${cryptolib}]) libtpms_cryptolib=${cryptolib} fi AC_MSG_RESULT($libtpms_cryptolib) if test "$libtpms_cryptolib" != "$cryptolib"; then echo "libtpms is using $libtpms_cryptolib; we have to use the same" if test "$cryptolib" = "openssl"; then AC_MSG_ERROR([do not use --with-openssl]) else AC_MSG_ERROR([use --with-openssl]) fi fi with_vtpm_proxy=no case $host_os in linux-*) with_vtpm_proxy=yes AC_DEFINE_UNQUOTED([WITH_VTPM_PROXY], 1, [whether to build in vTPM proxy support (Linux only)]) esac case $host_os in cygwin) CFLAGS="$CFLAGS -D__USE_LINUX_IOCTL_DEFS" esac dnl Seccomp profile using -lseccomp (Linux only) case $host_os in linux-*) with_seccomp_default=yes ;; *) with_seccomp_default=no ;; esac AC_MSG_CHECKING([for whether to build with seccomp profile]) AC_ARG_WITH([seccomp], AS_HELP_STRING([--with-seccomp],[build with seccomp profile]), AC_MSG_RESULT([$with_seccomp]), [with_seccomp=$with_seccomp_default] AC_MSG_RESULT([$with_seccomp]) ) if test "$with_seccomp" != "no"; then LIBSECCOMP_CFLAGS=$(pkg-config libseccomp --cflags 2>/dev/null) if test $? -ne 0; then AC_MSG_ERROR("Is libseccomp-devel installed? -- could not get cflags for libseccomp") else with_libseccomp=yes fi LIBSECCOMP_LIBS=$(pkg-config --libs libseccomp) AC_SUBST([LIBSECCOMP_LIBS]) AC_SUBST([LIBSECCOMP_CFLAGS]) AC_DEFINE_UNQUOTED([WITH_SECCOMP], 1, [whether to build in seccomp profile (Linux only)]) fi MY_CFLAGS="$CFLAGS" MY_LDFLAGS="$LDFLAGS" AC_SUBST([MY_CFLAGS]) AC_SUBST([MY_LDFLAGS]) AC_CONFIG_FILES([Makefile \ debian/swtpm-tools.postinst \ swtpm.spec \ etc/Makefile \ etc/swtpm_setup.conf \ samples/Makefile \ samples/swtpm-localca.conf \ samples/swtpm-create-user-config-files \ samples/swtpm_localca_conf.h \ include/Makefile \ include/swtpm/Makefile \ include/swtpm.h \ src/Makefile \ src/selinux/Makefile \ src/swtpm/Makefile \ src/swtpm_bios/Makefile \ src/swtpm_cert/Makefile \ src/swtpm_ioctl/Makefile \ src/swtpm_setup/Makefile \ src/swtpm_setup/swtpm_setup_conf.h \ src/utils/Makefile \ man/Makefile \ man/man3/Makefile \ man/man8/Makefile \ tests/Makefile \ tests/test_config \ ]) AC_OUTPUT echo printf "with_gnutls : %5s (no = swtpm_cert will NOT be built)\n" $with_gnutls printf "with_selinux : %5s (no = SELinux policy extensions will NOT be built)\n" $with_selinux printf "with_cuse : %5s (no = no CUSE interface)\n" $with_cuse printf "with_chardev : %5s (no = no chardev interface)\n" $with_chardev printf "with_vtpm_proxy : %5s (no = no vtpm proxy support; Linux only)\n" $with_vtpm_proxy printf "with_seccomp : %5s (no = no seccomp profile; Linux only)\n" $with_seccomp echo echo "Version to build : $PACKAGE_VERSION" echo "Crypto library : $cryptolib" echo echo " MY_CFLAGS = $MY_CFLAGS" echo " HARDENING_CFLAGS = $HARDENING_CFLAGS" echo "HARDENING_LDFLAGS = $HARDENING_LDFLAGS" echo " MY_LDFLAGS = $MY_LDFLAGS" echo " LIBSECCOMP_LIBS = $LIBSECCOMP_LIBS" echo " JSON_GLIB_CFLAGS = $JSON_GLIB_CFLAGS" echo " JSON_GLIB_LIBS = $JSON_GLIB_LIBS" echo " GLIB_CFLAGS = $GLIB_CFLAGS" echo " GLIB_LIBS = $GLIB_LIBS" echo echo "TSS_USER=$TSS_USER" echo "TSS_GROUP=$TSS_GROUP" echo swtpm-0.6.3/debian/000077500000000000000000000000001421141172300141105ustar00rootroot00000000000000swtpm-0.6.3/debian/changelog000066400000000000000000000041311421141172300157610ustar00rootroot00000000000000swtpm (0.6.3) RELEASED; urgency=low * Stable release -- Stefan Berger Mon, 07 Mar 2022 09:00:00 -0500 swtpm (0.6.2) RELEASED; urgency=medium * Stable release -- Stefan Berger Fri, 18 Feb 2022 09:00:00 -0500 swtpm (0.6.1) RELEASED; urgency=low * Stable release -- Stefan Berger Mon, 20 Sep 2021 09:00:00 -0500 swtpm (0.6.0) RELEASED; urgency=medium * Stable release -- Stefan Berger Mon, 07 Jun 2021 09:00:00 -0500 swtpm (0.6.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Fri, 09 Oct 2020 14:14:00 -0500 swtpm (0.5.0) RELEASED; urgency=medium * Stable release -- Stefan Berger Wed, 07 Oct 2020 11:27:00 -0500 swtpm (0.5.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Tue, 08 Sep 2020 09:00:00 -0500 swtpm (0.4.0-1) RELEASED; urgency=medium * Stable release -- Stefan Berger Fri, 28 Aug 2020 16:50:00 -0500 swtpm (0.4.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Tue, 07 Apr 2020 10:35:00 -0500 swtpm (0.3.0-1) RELEASED; urgency=medium * Release of swtpm-0.3.0 -- Stefan Berger Mon, 17 Feb 2020 09:00:00 -0500 swtpm (0.2.0-1) RELEASED; urgency=medium * Stable release -- Stefan Berger Tue, 16 Jul 2019 14:21:18 -0500 swtpm (0.2.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Mon, 04 Feb 2019 14:30:08 -0500 swtpm (0.1.0-1) RELEASED; urgency=medium * Initial public release -- Stefan Berger Mon, 28 Jan 2019 15:58:22 -0500 swtpm (0.1.0-1~dev2) RELEASED; urgency=medium * Developer release 2 -- Stefan Berger Mon, 13 Nov 2017 15:20:00 -0500 swtpm (0.1.0) UNRELEASED; urgency=medium * Under development -- Stefan Berger Tue, 12 Jan 2016 14:19:43 -0500 swtpm-0.6.3/debian/compat000066400000000000000000000000021421141172300153060ustar00rootroot0000000000000010swtpm-0.6.3/debian/control000066400000000000000000000036621421141172300155220ustar00rootroot00000000000000Source: swtpm Maintainer: Stefan Berger Section: misc Priority: optional Build-Depends: automake, autoconf, libtool, debhelper (>= 9), libtpms-dev, libfuse-dev, libglib2.0-dev, libjson-glib-dev, libgmp-dev, expect, libtasn1-dev, socat, python3-twisted, gnutls-dev, gnutls-bin, libssl-dev, net-tools, gawk, softhsm2, libseccomp-dev # linux-image-extra Package: swtpm Architecture: any Depends: swtpm-libs (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} # linux-image-extra Description: Libtpms-based TPM emulator The swtpm package provides TPM emulators that listen for TPM commands on sockets, character devices, or CUSE devices. Package: swtpm-libs Architecture: any Multi-Arch: same Depends: openssl, libtpms0, libglib2.0-0, ${shlibs:Depends}, ${misc:Pre-Depends}, ${misc:Depends} Description: Common libraries for TPM emulators The swtpm-libs package provides the shared libraries for the swtpm and swtpm-cuse packages. Package: swtpm-dev Architecture: any Depends: ${misc:Depends} Description: Include files for the TPM emulator's CUSE interface The swtpm-dev package provides include files for developing clients controlling the CUSE TPM through ioctls. Package: swtpm-tools Architecture: any Description: Tools for the TPM emulator The swtpm-tools package contains the following types of tools: - swtpm_bios: Tool for initializing the TPM - swtpm_ioctl: Tool for controlling the CUSE TPM - swtpm_setup: Tool for creating the initial state of the TPM; this tool basically simulates TPM manufacturing where certificates are written into the NVRAM of the TPM - swtpm_cert: Creation of certificates for the TPM (x509) Depends: swtpm (= ${binary:Version}), trousers (>= 0.3.9), ${shlibs:Depends}, ${misc:Depends}, gnutls-bin swtpm-0.6.3/debian/copyright000066400000000000000000000027431421141172300160510ustar00rootroot000000000000003-clause BSD license (c) Copyright IBM Corporation 2006, 2010. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the names of the IBM Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. swtpm-0.6.3/debian/rules000077500000000000000000000004341421141172300151710ustar00rootroot00000000000000#!/usr/bin/make -f %: dh $@ --parallel override_dh_auto_configure: NOCONFIGURE=1 ./autogen.sh dh_auto_configure -- --with-openssl --with-gnutls --without-cuse override_dh_usrlocal: override_dh_auto_test: SWTPM_TEST_SECCOMP_OPT="--seccomp action=none" make -j4 check VERBOSE=1 swtpm-0.6.3/debian/source/000077500000000000000000000000001421141172300154105ustar00rootroot00000000000000swtpm-0.6.3/debian/source/format000066400000000000000000000000151421141172300166170ustar00rootroot000000000000003.0 (native) swtpm-0.6.3/debian/swtpm-dev.install000066400000000000000000000001301421141172300174200ustar00rootroot00000000000000/usr/lib/*/swtpm/*.so /usr/include/swtpm/tpm_ioctl.h /usr/share/man/man3/swtpm_ioctls.3 swtpm-0.6.3/debian/swtpm-libs.install000066400000000000000000000000541421141172300176000ustar00rootroot00000000000000#! /usr/bin/dh-exec /usr/lib/*/swtpm/*.so.* swtpm-0.6.3/debian/swtpm-tools.install000077500000000000000000000012441421141172300200140ustar00rootroot00000000000000#!/bin/sh cat <<_EOF_ /usr/bin/swtpm_bios /usr/bin/swtpm_setup /usr/bin/swtpm_ioctl /usr/share/man/man8/swtpm_bios.8* /usr/share/man/man8/swtpm_cert.8* /usr/share/man/man8/swtpm_ioctl.8* /usr/share/man/man8/swtpm-localca.conf.8* /usr/share/man/man8/swtpm-localca.options.8* /usr/share/man/man8/swtpm-localca.8* /usr/share/man/man8/swtpm_setup.8* /usr/share/man/man8/swtpm_setup.conf.8* /usr/share/man/man8/swtpm_setup.sh.8* /usr/share/swtpm/swtpm-localca /usr/share/swtpm/swtpm-create-user-config-files /etc/swtpm-localca.conf /etc/swtpm-localca.options /etc/swtpm_setup.conf _EOF_ if test -n "$(find $(dirname "$0")/tmp -name swtpm_cert)"; then echo "/usr/bin/swtpm_cert" fi swtpm-0.6.3/debian/swtpm-tools.postinst.in000066400000000000000000000003161421141172300206320ustar00rootroot00000000000000#!/bin/sh SWTPM_LOCALCA_DIR=@LOCALSTATEDIR@/lib/swtpm-localca if ! [ -d $SWTPM_LOCALCA_DIR ]; then mkdir -p $SWTPM_LOCALCA_DIR chown @TSS_USER@:root $SWTPM_LOCALCA_DIR chmod 0750 $SWTPM_LOCALCA_DIR fi swtpm-0.6.3/debian/swtpm.install000066400000000000000000000001001421141172300166410ustar00rootroot00000000000000#! /usr/bin/dh-exec /usr/bin/swtpm /usr/share/man/man8/swtpm.8* swtpm-0.6.3/etc/000077500000000000000000000000001421141172300134415ustar00rootroot00000000000000swtpm-0.6.3/etc/Makefile.am000066400000000000000000000003021421141172300154700ustar00rootroot00000000000000# # etc/Makefile.am # # For the license, see the LICENSE file in the root directory. # swtpmsysconfdir = $(sysconfdir) swtpmsysconf_DATA = \ swtpm_setup.conf EXTRA_DIST= \ swtpm_setup.conf swtpm-0.6.3/etc/swtpm_setup.conf.in000066400000000000000000000003331421141172300173060ustar00rootroot00000000000000# Program invoked for creating certificates create_certs_tool= @DATAROOTDIR@/swtpm/swtpm-localca create_certs_tool_config = @SYSCONFDIR@/swtpm-localca.conf create_certs_tool_options = @SYSCONFDIR@/swtpm-localca.options swtpm-0.6.3/include/000077500000000000000000000000001421141172300143115ustar00rootroot00000000000000swtpm-0.6.3/include/Makefile.am000066400000000000000000000002701421141172300163440ustar00rootroot00000000000000# # include/Makefile.am # # For the license, see the COPYING file in the root directory. # SUBDIRS = swtpm noinst_HEADERS = \ sys_dependencies.h EXTRA_DIST = \ sys_dependencies.h swtpm-0.6.3/include/swtpm.h.in000066400000000000000000000035041421141172300162430ustar00rootroot00000000000000/* * swtpm.h * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SWTPM_TPM_H #define SWTPM_TPM_H #include #define SWTPM_VER_MAJOR @SWTPM_VER_MAJOR@ #define SWTPM_VER_MINOR @SWTPM_VER_MINOR@ #define SWTPM_VER_MICRO @SWTPM_VER_MICRO@ #endif /* SWTPM_TPM_H */ swtpm-0.6.3/include/swtpm/000077500000000000000000000000001421141172300154635ustar00rootroot00000000000000swtpm-0.6.3/include/swtpm/Makefile.am000066400000000000000000000002571421141172300175230ustar00rootroot00000000000000# # include/swtpm/Makefile.am # # For the license, see the COPYING file in the root directory. # swtpmincludedir = $(includedir)/swtpm swtpminclude_HEADERS = \ tpm_ioctl.h swtpm-0.6.3/include/swtpm/tpm_ioctl.h000066400000000000000000000236341421141172300176360ustar00rootroot00000000000000/* * tpm_ioctl.h * * (c) Copyright IBM Corporation 2014, 2015. * * This file is licensed under the terms of the 3-clause BSD license */ #ifndef _TPM_IOCTL_H_ #define _TPM_IOCTL_H_ #include #include #include #include /* * Every response from a command involving a TPM command execution must hold * the ptm_res as the first element. * ptm_res corresponds to the error code of a command executed by the TPM. */ typedef uint32_t ptm_res; /* PTM_GET_TPMESTABLISHED: get the establishment bit */ struct ptm_est { union { struct { ptm_res tpm_result; unsigned char bit; /* TPM established bit */ } resp; /* response */ } u; }; /* PTM_RESET_TPMESTABLISHED: reset establishment bit */ struct ptm_reset_est { union { struct { uint8_t loc; /* locality to use */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; /* PTM_INIT */ struct ptm_init { union { struct { uint32_t init_flags; /* see definitions below */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; /* above init_flags */ #define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0) /* delete volatile state file after reading it */ /* PTM_SET_LOCALITY */ struct ptm_loc { union { struct { uint8_t loc; /* locality to set */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; /* PTM_HASH_DATA: hash given data */ struct ptm_hdata { union { struct { uint32_t length; uint8_t data[4096]; } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; /* * size of the TPM state blob to transfer; x86_64 can handle 8k, * ppc64le only ~7k; keep the response below a 4k page size */ #define PTM_STATE_BLOB_SIZE (3 * 1024) /* * The following is the data structure to get state blobs from the TPM. * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads * with this ioctl and with adjusted offset are necessary. All bytes * must be transferred and the transfer is done once the last byte has been * returned. * It is possible to use the read() interface for reading the data; however, the * first bytes of the state blob will be part of the response to the ioctl(); a * subsequent read() is only necessary if the total length (totlength) exceeds * the number of received bytes. seek() is not supported. */ struct ptm_getstate { union { struct { uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */ uint32_t type; /* which blob to pull */ uint32_t offset; /* offset from where to read */ } req; /* request */ struct { ptm_res tpm_result; uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */ uint32_t totlength; /* total length that will be transferred */ uint32_t length; /* number of bytes in following buffer */ uint8_t data[PTM_STATE_BLOB_SIZE]; } resp; /* response */ } u; }; /* TPM state blob types */ #define PTM_BLOB_TYPE_PERMANENT 1 #define PTM_BLOB_TYPE_VOLATILE 2 #define PTM_BLOB_TYPE_SAVESTATE 3 /* state_flags above : */ #define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */ #define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */ /* * The following is the data structure to set state blobs in the TPM. * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple * 'writes' using this ioctl are necessary. The last packet is indicated * by the length being smaller than the PTM_STATE_BLOB_SIZE. * The very first packet may have a length indicator of '0' enabling * a write() with all the bytes from a buffer. If the write() interface * is used, a final ioctl with a non-full buffer must be made to indicate * that all data were transferred (a write with 0 bytes would not work). */ struct ptm_setstate { union { struct { uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */ uint32_t type; /* which blob to set */ uint32_t length; /* length of the data; use 0 on the first packet to transfer using write() */ uint8_t data[PTM_STATE_BLOB_SIZE]; } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; /* * PTM_GET_CONFIG: Data structure to get runtime configuration information * such as which keys are applied. */ struct ptm_getconfig { union { struct { ptm_res tpm_result; uint32_t flags; } resp; /* response */ } u; }; #define PTM_CONFIG_FLAG_FILE_KEY 0x1 #define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2 /* * PTM_SET_BUFFERSIZE: Set the buffer size to be used by the TPM. * A 0 on input queries for the current buffer size. Any other * number will try to set the buffer size. The returned number is * the buffer size that will be used, which can be larger than the * requested one, if it was below the minimum, or smaller than the * requested one, if it was above the maximum. */ struct ptm_setbuffersize { union { struct { uint32_t buffersize; /* 0 to query for current buffer size */ } req; /* request */ struct { ptm_res tpm_result; uint32_t buffersize; /* buffer size in use */ uint32_t minsize; /* min. supported buffer size */ uint32_t maxsize; /* max. supported buffer size */ } resp; /* response */ } u; }; #define PTM_GETINFO_SIZE (3 * 1024) /* * PTM_GET_INFO: Get info about the TPM implementation (from libtpms) * * This request allows to indirectly call TPMLIB_GetInfo(flags) and * retrieve information from libtpms. * Only one transaction is currently necessary for returning results * to a client. Therefore, totlength and length will be the same if * offset is 0. */ struct ptm_getinfo { union { struct { uint64_t flags; uint32_t offset; /* offset from where to read */ uint32_t pad; /* 32 bit arch */ } req; /* request */ struct { ptm_res tpm_result; uint32_t totlength; uint32_t length; char buffer[PTM_GETINFO_SIZE]; } resp; /* response */ } u; }; #define SWTPM_INFO_TPMSPECIFICATION ((uint64_t)1 << 0) #define SWTPM_INFO_TPMATTRIBUTES ((uint64_t)1 << 1) typedef uint64_t ptm_cap; typedef struct ptm_est ptm_est; typedef struct ptm_reset_est ptm_reset_est; typedef struct ptm_loc ptm_loc; typedef struct ptm_hdata ptm_hdata; typedef struct ptm_init ptm_init; typedef struct ptm_getstate ptm_getstate; typedef struct ptm_setstate ptm_setstate; typedef struct ptm_getconfig ptm_getconfig; typedef struct ptm_setbuffersize ptm_setbuffersize; typedef struct ptm_getinfo ptm_getinfo; /* capability flags returned by PTM_GET_CAPABILITY */ #define PTM_CAP_INIT (1) #define PTM_CAP_SHUTDOWN (1 << 1) #define PTM_CAP_GET_TPMESTABLISHED (1 << 2) #define PTM_CAP_SET_LOCALITY (1 << 3) #define PTM_CAP_HASHING (1 << 4) #define PTM_CAP_CANCEL_TPM_CMD (1 << 5) #define PTM_CAP_STORE_VOLATILE (1 << 6) #define PTM_CAP_RESET_TPMESTABLISHED (1 << 7) #define PTM_CAP_GET_STATEBLOB (1 << 8) #define PTM_CAP_SET_STATEBLOB (1 << 9) #define PTM_CAP_STOP (1 << 10) #define PTM_CAP_GET_CONFIG (1 << 11) #define PTM_CAP_SET_DATAFD (1 << 12) #define PTM_CAP_SET_BUFFERSIZE (1 << 13) #define PTM_CAP_GET_INFO (1 << 14) #define PTM_CAP_SEND_COMMAND_HEADER (1 << 15) enum { PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), PTM_INIT = _IOWR('P', 1, ptm_init), PTM_SHUTDOWN = _IOR('P', 2, ptm_res), PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est), PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc), PTM_HASH_START = _IOR('P', 5, ptm_res), PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata), PTM_HASH_END = _IOR('P', 7, ptm_res), PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res), PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res), PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est), PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate), PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate), PTM_STOP = _IOR('P', 13, ptm_res), PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), PTM_SET_DATAFD = _IOR('P', 15, ptm_res), PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), PTM_GET_INFO = _IOWR('P', 17, ptm_getinfo), }; /* * Commands used by the non-CUSE TPMs * * All messages container big-endian data. * * The return messages only contain the 'resp' part of the unions * in the data structures above. Besides that the limits in the * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data * and ptm_set_state:u.req.data) are 0xffffffff. */ enum { CMD_GET_CAPABILITY = 1, /* 0x01 */ CMD_INIT, /* 0x02 */ CMD_SHUTDOWN, /* 0x03 */ CMD_GET_TPMESTABLISHED, /* 0x04 */ CMD_SET_LOCALITY, /* 0x05 */ CMD_HASH_START, /* 0x06 */ CMD_HASH_DATA, /* 0x07 */ CMD_HASH_END, /* 0x08 */ CMD_CANCEL_TPM_CMD, /* 0x09 */ CMD_STORE_VOLATILE, /* 0x0a */ CMD_RESET_TPMESTABLISHED, /* 0x0b */ CMD_GET_STATEBLOB, /* 0x0c */ CMD_SET_STATEBLOB, /* 0x0d */ CMD_STOP, /* 0x0e */ CMD_GET_CONFIG, /* 0x0f */ CMD_SET_DATAFD, /* 0x10 */ CMD_SET_BUFFERSIZE, /* 0x11 */ CMD_GET_INFO, /* 0x12 */ }; #endif /* _TPM_IOCTL_H */ swtpm-0.6.3/include/sys_dependencies.h000066400000000000000000000046151421141172300200140ustar00rootroot00000000000000/* * sys_dependencies.h -- system specific includes and #defines * * (c) Copyright IBM Corporation 2018. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SWTPM_SYS_DEPENDENCIES_H #define SWTPM_SYS_DEPENDENCIES_H #if !defined __OpenBSD__ && !defined __FreeBSD__ && !defined __NetBSD__ \ && !defined __APPLE__ && !defined __DragonFly__ #define _GNU_SOURCE #include #endif #if defined __FreeBSD__ || defined __NetBSD__ || defined __DragonFly__ # include # include #elif defined __APPLE__ # include # define be16toh(x) OSSwapBigToHostInt16(x) # define be32toh(x) OSSwapBigToHostInt32(x) # define be64toh(x) OSSwapBigToHostInt64(x) # define htobe16(x) OSSwapHostToBigInt16(x) # define htobe32(x) OSSwapHostToBigInt32(x) # define htobe64(x) OSSwapHostToBigInt64(x) #else # include #endif #endif /* SWTPM_SYS_DEPENDENCIES_H */swtpm-0.6.3/man/000077500000000000000000000000001421141172300134415ustar00rootroot00000000000000swtpm-0.6.3/man/Makefile.am000066400000000000000000000001621421141172300154740ustar00rootroot00000000000000# # man/Makefile.am # # For the license, see the COPYING file in the root directory. # SUBDIRS = \ man3 \ man8 swtpm-0.6.3/man/man3/000077500000000000000000000000001421141172300142775ustar00rootroot00000000000000swtpm-0.6.3/man/man3/Makefile.am000066400000000000000000000004371421141172300163370ustar00rootroot00000000000000# # man/man3/Makefile.am # # For the license, see the COPYING file in the root directory. # man3_PODS = \ swtpm_ioctls.pod man3_MANS = \ swtpm_ioctls.3 %.3 : %.pod @pod2man -r "swtpm" \ -c "" \ -n $(basename $@) \ --section=3 $< > $@ EXTRA_DIST = $(man3_MANS) $(man3_PODS) swtpm-0.6.3/man/man3/swtpm_ioctls.pod000066400000000000000000000306351421141172300175410ustar00rootroot00000000000000=head1 NAME swtpm_ioctls - Description of the ioctl's of the CUSE TPM (swtpm_cuse) and control commands used by the control channel over socket interface. =head1 SYNOPSYS B<#include Etpm_ioctl.hE> =head1 DESCRIPTION The CUSE TPM implements an ioctl interface on the CUSE TPM's character device. The ioctl's are used for out-of-band control of various TPM operations, such as its initialization, resetting, and state migration. The control channel over TCP or UnixIO sockets uses control commands for these operations. The following is an enumeration of the supported ioctl's and control commands, along with the names of the data structure types. All ioctl's and control commands return a TPM error code in their response. Ioctl's are prefixed with I and control commands are prefixed with I. In case of the ioctl interface, the pointer to a command's data structure is passed as the 2nd parameter to the ioctl() function. The fields in the command's data structure are to be fill out in host endianness format. In case of control commands, the command code must be encoded as a 4 byte integer preceding the command's data structure. Command code and data must be written in big endian format. =over 4 =item B This ioctl allows the caller to check which ioctl's are implemented by the CUSE TPM. The following is a list of capability flags that may be set upon return: =over 4 =item B The PTM_INIT ioctl or CMD_INIT command is supported. =item B The PTM_SHUTDOWN ioctl or CMD_SHUTDOWN command is supported. =item B The PTM_GET_TPMESTABLISHED ioctl or CMD_GET_TPMESTABLISHED command is supported. =item B The PTM_SET_LOCALITY ioctl or CMD_SET_LOCALITY is supported. =item B The PTM_HASH_START, PTM_HASH_DATA, and PTM_HASH_END ioctl's or CMD_HASH_START, CMD_HASH_DATA, CMD_HASH_END commands are supported. =item B The PTM_CANCEL_TPM_CMD ioctl or CMD_CANCEL_TPM_CMD command is supported. =item B The PTM_STORE_VOLATILE ioctl or CMD_STORE_VOLATILE command is supported. =item B The PTM_RESET_TPMESTABLISHED ioctl or CMD_RESET_TPMESTABLISHED command is supported. =item B The PTM_GET_STATEBLOB ioctl or CMD_GET_STATEBLOB command is supported. =item B The PTM_SET_STATEBLOB ioctl or CMD_SET_STATEBLOB command is supported. =item B The PTM_STOP ioctl or CMD_STOP command is supported. =item B The PTM_GET_CONFIG ioctl or CMD_GET_CONFIG command is supported. =item B The CMD_SET_DATAFD command is supported. This command only applies to UnixIO and there is no support for PTM_SET_DATAFD. =item B The PTM_SET_BUFFERSIZE ioctl or CMD_SET_BUFFERSIZE command is supported. =back =item B This ioctl must be used to initialize the TPM. It must be sent to the TPM before any TPM command is sent. The ptm_init data structure looks as follows: struct ptm_init { union { struct { uint32_t init_flags; /* see definitions below */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; The init_flags field in the request can be used to have the TPM delete the volatile state upon startup (B). A TPM result code is returned in the tpm_result field. =item B This ioctl allows a user to shut down the TPM. A TPM result code is returned in ptm_res. =item B This ioctl is used to check whether the TPM established flag is set. The tpm_est data structure looks as follows: struct ptm_est { union { struct { ptm_res tpm_result; unsigned char bit; /* TPM established bit */ } resp; /* response */ } u; }; A TPM result code is returned in the tpm_result field. The status of the TPM establishment flag is returned in the bit field. =item B This ioctl is used to set the current locality. All subsequent commands will be executed in this locality until the locality is changed. The ptm_loc data structure looks as follows: struct ptm_loc { union { struct { uint8_t loc; /* locality to set */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; The locality number must be set in the request's loc field. Valid localities are in the range of 0 to 4. A TPM result code is returned in the tpm_result field. =item B This ioctl is used to start the hash operation that is typically initiated by writing into certain registers of locality 4 of the TPM Interface (TPM TIS). Subsequent write operations for transferring data must be done with the B ioctl. A TPM result code is returned in ptm_res. =item B This command is used to transfer the data for the hash operation. The ptm_hdata structure looks as follows: struct ptm_hdata { union { struct { uint32_t length; uint8_t data[4096]; } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; The length of the data is indicated in the length field with the data in the data field. Up to 4096 bytes can be transferred in one call. A TPM result code is returned in the tpm_result field. =item B This command is used to indicate the end of a hash operation that was started with the B ioctl. A TPM result code is returned in ptm_res. =item B This command is used to cancel a TPM command. A TPM result code is returned in ptm_res. =item B This command is used to trigger the TPM to store the volatile state into a file. A TPM result code is returned in ptm_res. =item B This command is used to reset the TPM's establishment flag. The ptm_reset_est data structure looks as follows: struct ptm_reset_est { union { struct { uint8_t loc; /* locality to use */ } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; The locality in which the establishment flag is to be reset must be set in the loc field. Valid localities are in the range of 0 to 4. A TPM result code is returned in the tpm_result field. =item B This command is used to initiate the retrieval of one of the TPM's stateblobs. The ptm_getstate data structure looks as follows: struct ptm_getstate { union { struct { uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */ uint32_t type; /* which blob to pull */ uint32_t offset; /* offset from where to read */ } req; /* request */ struct { ptm_res tpm_result; uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */ uint32_t totlength; /* total length that will be transferred */ uint32_t length; /* number of bytes in following buffer */ uint8_t data[PTM_STATE_BLOB_SIZE]; } resp; /* response */ } u; }; In the request the state_flags field allows a user to set the B flag to retrieve decrypted TPM state in case the TPM's state was written in encrypted form. The type field allows a user to choose one of the TPM's state blobs, and must be one of B, B, and B. The offset field indicates at what offset to read the data from. Subsequent state transfers must advance the offset field to the next byte to be read. If the read() interface is used the offset will be advanced automatically. The response returns a TPM error code in the tpm_result field. The state_flags field in the response indicates whether the returned blob is encrypted. The totlength field indicates the total length of the state blob. The length field indicates the number of valid bytes in the data field. If necessary, subsequent state blob transfers must be done using this ioctl or using the read() call on the file descriptor. All state must be transferred before the TPM will accept commands again. =item B This command is used to transfer one of the TPM's stateblob to the TPM. The ptm_setstate data structure looks as follows: struct ptm_setstate { union { struct { uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */ uint32_t type; /* which blob to set */ uint32_t length; /* length of the data; use 0 on the first packet to transfer using write() */ uint8_t data[PTM_STATE_BLOB_SIZE]; } req; /* request */ struct { ptm_res tpm_result; } resp; /* response */ } u; }; The state_flags field indicates whether the provided state is encrypted. In case it is encrypted, a migration key must have been provided to the TPM for it to be able to decrypt the state. The type field indicates which one of the TPM's state blobs is being set. It must be either one of B, B, and B. The length field indicates the number of bytes of state blob data in the data field. To transfer the state blob using the write() call, set the length to 0. The response returns a TPM error code in the tpm_result field. =item B This command is used to stop the TPM. In contrast to a TPM shut down, the stopping of the TPM only halts its operations without terminating the TPM process. The TPM can restart operation with the B ioctl. A TPM result code is returned in ptm_res. =item B This command is used to retrieve the TPM's current configuration. The ptm_getconfig data structure looks as follows: struct ptm_getconfig { union { struct { ptm_res tpm_result; uint32_t flags; } resp; /* response */ } u; }; A TPM result code is returned in the tpm_result field. The flags field holds individual flags that indicate whether a file encryption key is used (B) and whether a migration key is used (B). =item B This command is only implemented for the control channel over UnixIO socket. It is used to establish the TPM command channel by transferring a socket file descriptor using the UnixIO socket's control channel and I. See also B and B. A TPM result code is returned in ptm_res. =item B This command allows a user to set and query for the buffer size that the TPM is using for input and output I/O buffers. The ptm_setbuffersize data structure looks as follows: struct ptm_setbuffersize { union { struct { uint32_t buffersize; /* 0 to query for current buffer size */ } req; /* request */ struct { ptm_res tpm_result; uint32_t buffersize; /* buffer size in use */ uint32_t minsize; /* min. supported buffer size */ uint32_t maxsize; /* max. supported buffer size */ } resp; /* response */ } u; }; If a 0 is set in the buffer size of the request, the response will return the buffer size that is currently in use. Any other number will try to change the buffer size, but the TPM may adjust it to an allowed minimum or maximum. The minimum and maximum supported buffer sizes are returned in the response. The buffersize can only be changed when the TPM is stopped. The currently used buffersize can be read at any time. =back =head1 SEE ALSO B, B swtpm-0.6.3/man/man8/000077500000000000000000000000001421141172300143045ustar00rootroot00000000000000swtpm-0.6.3/man/man8/Makefile.am000066400000000000000000000013771421141172300163500ustar00rootroot00000000000000# # man/man8/Makefile.am # # For the license, see the COPYING file in the root directory. # man8_PODS = \ swtpm.pod \ swtpm_bios.pod \ swtpm_cert.pod \ swtpm_cuse.pod \ swtpm_ioctl.pod \ swtpm_setup.pod \ swtpm_setup.conf.pod swtpm-create-tpmca.pod \ swtpm-localca.pod \ swtpm-localca.options.pod \ swtpm-localca.conf.pod man8_MANS = \ swtpm.8 \ swtpm_bios.8 \ swtpm_cert.8 \ swtpm_ioctl.8 \ swtpm_setup.8 \ swtpm_setup.conf.8 \ swtpm_setup.sh.8 \ swtpm-create-tpmca.8 \ swtpm-localca.8 \ swtpm-localca.options.8 \ swtpm-localca.conf.8 if WITH_CUSE man8_MANS += \ swtpm_cuse.8 endif %.8 : %.pod @pod2man -r "swtpm" \ -c "" \ -n $(basename $@) \ --section=8 $< > $@ EXTRA_DIST = $(man8_MANS) $(man8_PODS) CLEANFILES = swtpm_cuse.8 swtpm-0.6.3/man/man8/swtpm-create-tpmca.pod000066400000000000000000000145551421141172300205370ustar00rootroot00000000000000=head1 NAME swtpm-create-tpmca =head1 SYNOPSIS B =head1 DESCRIPTION B is a tool to create a TPM 1.2 based CA that can be used by B to sign EK and platform certificates. The CA uses a GnuTLS key to sign certificates. To do this, GnuTLS talks to the TPM 1.2 using the B (TrouSerS) daemon. Since the TPM CA's certificate must be signed by a CA, a root certificate authority will also be created and will sign this certificate. The root CA's private key and certificate will be located in the same directory as the signing key and have the names swtpm-localca-rootca-privkey.pem and swtpm-localca-rootca-cert.pem respectively. The environment variable SWTPM_ROOTCA_PASSWORD can be set for the password of the root CA's private key. Note: This tool is experimental. See the section on known issues below. The following options are supported: =over 4 =item B<--dir dir> The directory where the keys will be written to. An existing root CA with the files I and I in this directory will be reused. If either one of these files does not exist, a new root CA will be created. =item B<--overwrite> Overwrite the contents of the output directory. =item B<--register> Register the key with TCSD. For the key to be available for signing, the same user that created the TPM CA has to run the swtpm-localca later on. If this option is not passed, the private key is written into a file and can be used by others as well. =item B<--key-password s> The new signing key will get this password. Note: Due to a bug in GnuTLS certtool it may be necessary to use the same password for the signing key as for the SRK. =item B<--srk-password s> The TPM SRK password. Note: Since GnuTLS tpmtool does not support the 'well known' password of 20 zero bytes, the SRK password must be set. =item B<--outfile filename> The name of a file where to write the swtpm-localca.conf configuration to. =item B<--owner owner> The name or uid number of the owner who will own the directory and outfile file. This option only has an effect if this swtpm-create-tpmca is run by the root user. =item B<--group group> The name or gid number of the group who will own the directory and outfile file. This option only has an effect if this swtpm-create-tpmca is run by the root user. =item B<--tss-tcsd-hostname> The hostname where tcsd is running on. The default hostname is 'localhost'. =item B<-tss-tcsd-port> The TCP port on which tcsd is listening for messages. The default port is 30003. =item B<--tpm2> The TPM to use for signing the certificates is a TPM 2 and Intel's TSS stack must be running (tpm2-abrmd) along with its PKCS11 module. The TPM 2 PKCS11 module must have been initialized using the tpm2_ptool. The environment variables SWTPM_PKCS11_PIN and SWTPM_PKCS11_SO_PIN should be set to hold the PINs. If SWTPM_PKCS11_PIN is not set then the default PIN 'swtpm-tpmca' will be used. SWTPM_PKCS11_SO_PIN is needed for creating the token and must be explicitly set as an environment variable. =item B<--pid pimary-object-id> The primary object id that the tpm2_ptool returns upon 'init'. =item B<-help, -h, -?> Display the help screen and exit. =back =head1 EXAMPLE The following example creates an intermediate TPM CA and writes the keys into /var/lib/swtpm-localca and the swtpm-localca configuration to /etc/swtpm-localca.conf. It can then be used for signing certificates of newly created B TPMs. If the host's TPM is a TPM 1.2, we need to start the tcsd first and can then create the TPM key and TPM CA certificate: #> sudo systemctl start tcsd #> sudo /usr/share/swtpm/swtpm-create-tpmca \ --dir /var/lib/swtpm-localca \ --overwrite \ --outfile /etc/swtpm-localca.conf \ --srk-password password \ --key-password password \ --group tss statedir = /var/lib/swtpm-localca signingkey = tpmkey:file=/var/lib/swtpm-localca/swtpm-localca-tpmca-privkey.pem issuercert = /var/lib/swtpm-localca/swtpm-localca-tpmca-cert.pem certserial = /var/lib/swtpm-localca/certserial TSS_TCSD_HOSTNAME = localhost TSS_TCSD_PORT = 30003 signingkey_password = password parentkey_password = password Alternatively, if the host's TPM is a TPM 2 and Intel's TPM 2 stack is installed, we need to start tpm2-abrmd first and can then create the TPM key and TPM CA certificate: #> sudo systemctl start tpm2-abrmd #> tpm2_ptool init action: Created id: 1 # this is the --pid parameter below #> sudo SWTPM_PKCS11_PIN="mypin 123" SWTPM_PKCS11_SO_PIN=123 /usr/share/swtpm/swtpm-create-tpmca \ --dir /var/lib/swtpm-localca \ --overwrite \ --outfile /etc/swtpm-localca.conf \ --group tss \ --tpm2 \ --pid 1 statedir = /var/lib/swtpm-localca signingkey = pkcs11:model=SW%20%20%20TPM\;manufacturer=IBM\;serial=0000000000000000\;token=swtpm-tpmca-1\;id=%31\;object=swtpm-tpmca-key\;type=private issuercert = /var/lib/swtpm-localca/swtpm-localca-tpmca-cert.pem certserial = /var/lib/swtpm-localca/certserial SWTPM_PKCS11_PIN = mypin 123 Note: This also works for non-root users by adapting the --dir and --outfile parameters here and below by changing the --dir parameter and adding a --config parameter. To test either one of the above TPM CAs, run the following command: #> /usr/share/swtpm/swtpm-localca \ --type ek --ek x=11,y=13 \ --dir /tmp --vmid test --tpm2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \ --tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM The --tpm2 in this command indicates that the TPM for which the certificate is created is a TPM 2. =head1 KNOWN ISSUES The interaction of GnuTLS certtool with the TPM TCSD daemon may cause so many TPM (key) authentication failures that the TPM refuses to accept any more authenticated commands until the TPM's owner sends it the TPM_ORD_ResetLockValue command. The reason for this is that certtool first tries to use 20 zero bytes for the SRK password and only then prompts for and uses the required SRK password. The GnuTLS tpmtool does not support 20 zero bytes for the SRK password, so forces the usage of a 'real' password. The effect of the authentication failures may be that the TPM CA cannot sign certificates since the TPM does not accept authenticated commands. =head1 SEE ALSO B, B, B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm-localca.conf.pod000066400000000000000000000046411421141172300205070ustar00rootroot00000000000000=head1 NAME swtpm-localca.conf - Configuration file for swtpm-localca =head1 DESCRIPTION The file I contains configuration variables for the I program. Entries may contain environment variables that will be resolved. All environment variables must be formatted like this: '${varname}'. Users may write their own configuration into I<${XDG_CONFIG_HOME}/swtpm-localca.conf> or if XDG_CONFIG_HOME is not set it may be in I<${HOME}/.config/swtpm-localca.conf>. The following configuration variables are supported: =over 4 =item B The name of a directory where to store data into. A lock will be created in this directory. =item B The file containing the key used for signing the certificates. Provide a key in PEM format or a pkcs11 URI. =item B The password to use for the signing key. =item B The file containing the certificate for this CA. Provide a certificate in PEM format. =item B The name of file containing the serial number for the next certificate. =item B This variable can be set to the host where B is running on in case the signing key is a GnuTLS TPM 1.2 key. By default I will be used. =item B This variable can be set to the port on which B is listening for connections. By default port I<30003> will be used. =item B=> Environment variables, that are needed by pkcs11 modules, can be set using this format. An example for such an environment variable may look like this: env:MY_MODULE_PKCS11_CONFIG = /tmp/mymodule-pkcs11.conf The line must not contain any trailing spaces. =back =head1 EXAMPLE An example I file may look as follows: statedir = /var/lib/swtpm_localca signingkey = /var/lib/swtpm_localca/signkey.pem issuercert = /var/lib/swtpm_localca/issuercert.pem certserial = /var/lib/swtpm_localca/certserial With a PKCS11 URI it may look like this: statedir = /var/lib/swtpm-localca signingkey = pkcs11:model=SoftHSM%20v2;manufacturer=SoftHSM%20project;serial=891b99c169e41301;token=mylabel;id=%00;object=mykey;type=public issuercert = /var/lib/swtpm-localca/swtpm-localca-tpmca-cert.pem certserial = /var/lib/swtpm-localca/certserial SWTPM_PKCS11_PIN = 1234 =head1 SEE ALSO B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm-localca.options.pod000066400000000000000000000013641421141172300212540ustar00rootroot00000000000000=head1 NAME swtpm-localca.options - Options file for swtpm-localca =head1 DESCRIPTION The file I contains command line options to pass to the I program and should hold options that apply to the creation of all TPM Endorsement Key (EK) and platform certificates. Users may write their own options into I<${XDG_CONFIG_HOME}/swtpm-localca.options> or if XDG_CONFIG_HOME is not set it may be in I<${HOME}/.config/swtpm-localca.options>. =head1 EXAMPLE An example I file may look as follows: --platform-manufacturer Fedora --platform-version 2.1 --platform-model QEMU =head1 SEE ALSO B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm-localca.pod000066400000000000000000000073041421141172300175620ustar00rootroot00000000000000=head1 NAME swtpm-localca - Local CA to create EK and platform certs for swtpm =head1 SYNOPSIS B =head1 DESCRIPTION B is a tool to create TPM Endorsement Key (EK) and platform certificates on the host. It uses the I program to create the certificates. The program will typically be invoked by the I program that uses the I configuration file where a variable needs to be set that points to this program. It implements command line options that the I program uses to provide the necessary parameters to it. B will automatically try to create the signing key and certificate if the configuration points to a missing signing key. Since this certificate must be signed by a CA, a root certificate authority will also be created and will sign this certificate. The root CA's private key and certificate will be located in the same directory as the signing key and have the names swtpm-localca-rootca-privkey.pem and swtpm-localca-rootca-cert.pem respectively. The environment variable SWTPM_ROOTCA_PASSWORD can be set for the password of the root CA's private key. Note: Due to limitations of 'certtool', the possible passwords used for securing the root CA's private key and the intermedia CA's private key have to be passed over the command line and therefore will be visible to others on the system. If you are concerned about this, you should create the CAs elsewhere and copy them onto the target system. The following options are supported: =over 4 =item B<--type type> This parameter indicates the type of certificate to create. The type parameter may be one of the following: I, or I =item B<--dir dir> This parameter indicates the directory into which the certificate is to be stored. The EK certificate is stored in this directory under the name ek.cert and the platform certificate under the name platform.cert. =item B<--ek ek> This parameter indicates the modulus of the public key of the endorsement key (EK). The public key is provided as a sequence of ASCII hex digits. In case ECC (elliptic curve crypography) keys are used, the parameter must have the format --ek x=,y=,id=. The id= part is optional and only necessary for ECC curves other than secp256r1. =item B<--vmid ID> This parameter indicates the ID of the VM for which to create the certificate. =item B<--logfile > The log file to log output to; by default logging goes to stdout and stderr on the console. =item B<--configfile > The configuration file to use. If omitted, the default configuration file I will be used. =item B<--optsfile > The options file to use. If omitted, the default options file I will be used. =item B<--tpm-spec-family>, B<--tpm-spec-revision>, B<--tpm-spec-level> TPM specification parameters that describe the specification that was followed for the TPM implementation. The parameters will be passed to swtpm_cert for the creation of the EK certificate. =item B<--tpm2> Create TPM 2 compliant certificates. =item B<--allow-signing> Create an EK that can also be used for signing. Without this option, the EK can only be used for key encipherment. This option requires --tpm2. =item B<--decryption> If --allow-signing is passed and the EK should also be useable for key encipherment, this option must be passed. Otherwise key encipherment is the default. This option requires --tpm2. =back =head1 SEE ALSO B, B, B, B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm.pod000066400000000000000000000304261421141172300161670ustar00rootroot00000000000000=head1 NAME swtpm - TPM Emulator for TPM 1.2 and 2.0 =head1 SYNOPSIS B B B =head1 DESCRIPTION B implements a TPM software emulator built on libtpms. It provides access to TPM functionality over a TCP/IP socket interface or it can listend for commands on a character device, or create a CUSE (character device in userspace) interface for receiving of TPM commands. Unless corresponding command line parameters are used, the B socket version requires that the environment variable I be set to the TCP/IP port the process is supposed to listen on for TPM request messages. Similarly, the environment variable I can be set and contain the name of a directory where the TPM can store its persistent state into. The B process can be gracefully terminated by sending a I signal to it. The B cuse version requires root rights to start the TPM. =head1 Options for socket interface The following options are supported if the I interface is chosen: =over 4 =item B<-p|--port > Use the given port rather than using the environment variable TPM_PORT. =item B<-t|--terminate> Terminate the TPM after the client has closed the connection. =item B<--server [type=tcp][,port=EportE[,bindaddr=EaddressE [,ifname=EifnameE]]][,fd=EfdE][,disconnect]> Expect TCP connections on the given port; if a port is not provided a file descriptor must be passed with the fd parameter and the commands are read from this file descriptor then. If a port is provided the I on which to listen for TCP connections can be provided as well; the default bind address is 127.0.0.1. If a link local IPv6 address is provided, the name of the interface to bind to must be provided with I. This parameter enables a persistent connection by default unless the disconnect option is given. This parameter should be used rather than the -p and --fd options. =item B<--server type=unixio[,path=EpathE][,fd=EfdE] [,mode=E0...E][,uid=EuidE][,gid=EgidE]> Expect UnixIO connections on the given path. If no path is provided, a file descriptor must be passed instead. The mode parameter allows a user to set the file mode bits of the UnixIO path. The mode bits value must be given as an octal number starting with a '0'. The default value is 0770. uid and gid set the ownership of the UnixIO socket's path. This operation requires root privileges. =back =head1 Options for character device interface The following options are supported if the I interface is chosen: =over 4 =item B<-c|--chardev > Use the given device to listen for TPM commands and send response on. =item B<--vtpm-proxy> Create a Linux vTPM proxy device instance and read TPM commands from its backend device. =back =head1 Options for the CUSE interface The following options are supported if the I interface is chosen: =over 4 =item B<-n|--name > The TPM will use a device with the given name. A device with the given name will be created in /dev. This is a mandatory option. =item B<-M|--maj > Create the device with the given major number. =item B<-m|--min > Create the device with the given minor number. =back =head1 Options for socket and character device interfaces: The following options are supported by the socket and character device interfaces: =over 4 =item B<-f|--fd > Use the given socket file descriptor or character device file descriptor for receiving TPM commands and sending responses. For the socket interface, this option automatically assumes -t. =item B<-d|--daemon> Daemonize the process. =item B<--ctrl type=[unixio|tcp][,path=EpathE] [,port=EportE[,bindaddr=EaddressE[,ifname=EifnameE]]] [,fd=EfiledescriptorE|clientfd=EfiledescriptorE] [,mode=E0...E][,uid=EuidE][,gid=EgidE] > This option adds a control channel to the TPM. The control channel can either use a UnixIO socket with a given I or I or it can use a TCP socket on the given I or I. If a port is provided the I on which to listen for TCP connections can be provided as well; the default bind address is 127.0.0.1. If a link local IPv6 address is provided, the name of the interface to bind to must be provided with I. The mode parameter allows a user to set the file mode bits of the UnixIO path. The mode bits value must be given as an octal number starting with a '0'. The default value is 0770. uid and gid set the ownership of the UnixIO socket's path. This operation requires root privileges. The control channel enables out-of-band control of the TPM, such as resetting the TPM. =back =head1 Options for all interfaces The following options are support by all interfaces: =over 4 =item B<--tpmstate dir=EdirE[,mode=E0...E]> Use the given path rather than using the environment variable TPM_PATH. The TPM state files will be written with the given file mode bits. This value must be given as an octal number starting with a '0'. The default value is 0640. =item B<--tpm2> Choose TPM 2 functionality; by default a TPM 1.2 is chosen. =item B<--log [fd=EfdE|file=EpathE][,level=EnE] [,prefix=EprefixE][,truncate]> Enable logging to a file given its file descriptor or its path. Use '-' for path to suppress the logging. The level parameter allows a user to choose the level of logging. Starting at log level 5, libtpms debug logging is activated. All logged lines will be prefixed with prefix. By default no prefix is prepended. If I is passed, the log file will be truncated. =item B<--locality reject-locality-4[,allow-set-locality]> The I parameter will cause TPM error messages to be returned for requests to set the TPM into locality 4. The I parameter allows the swtpm to receive TPM/TPM2_SetLocality commands. This is parameter is useful if the Linux VTPM proxy driver access is enabled by file descriptor passing. This option is implied by the I<--vtpm-proxy> option and therefore need not be explicitly set if this option is passed. In all other cases care should be taken as to who can send the TPM/TPM2_SetLocality command. =item B<--key file=EkeyfileE|fd=EfdE [,format=Ehex|binaryE][,mode=aes-cbc|aes-256-cbc], [remove[=true|false]]> Enable encryption of the state files of the TPM. The keyfile must contain an AES key of supported size; 128 bit (16 bytes) and 256 bit (32 bytes) keys are supported. The key may be in binary format, in which case the file size must be 16 or 32 bytes. If the key is in hex format (default), the key may consist of 32 or 64 hex digits starting with an optional '0x'. The I parameter indicates which block chaining mode is to be used. Currently aes-cbc (aes-128-cbc) and aes-256-cbc are supported. The encrypted data is integrity protected using encrypt-then-mac. The I parameter will attempt to remove the given keyfile once the key has been read. =item B<--key pwdfile=Epassphrase fileE|pwdfd=EfdE [,mode=aes-cbc|aes-256-cbc][remove[=true|false]][,kdf=sha512|pbkdf2]> This variant of the key parameter allows a user to provide a passphrase in a file. The file is read and a key is derived from it using either a SHA512 hash or PBKDF2. By default PBKDF2 is used. =item B<--migration-key file=EkeyfileE|fd=EfdE [,format=Ehex|binaryE][,mode=aes-cbc|aes-256-cbc] [,remove[=true|false]]> The availability of a migration key ensures that the state of the TPM will not be revealed in unencrypted form when the TPM state blobs are retrieved through the ioctl interface. The migration key is not used for encrypting TPM state written to files, this is what the I<--key> parameter is used for. The migration key and the key used for encrypting the TPM state files may be the same. While the key for the TPM state files needs to stay with those files it encrypts, the migration key needs to stay with the TPM state blobs. If for example the state of the TPM is migrated between hosts in a data center, then the TPM migration key must be available at all the destinations, so in effect it may have to be a key shared across all machines in the datacenter. In contrast to that, the key used for encrypting the TPM state B can be different for each TPM and need only be available on the host where the TPM state resides. The migration key enables the encryption of the TPM state blobs. The keyfile must contain an AES key of supported size; 128 bit (16 bytes) and 256 bit (32 bytes) keys are supported. The key may be in binary format, in which case the file size must be 16 or 32 bytes. If the key is in hex format (default), the key may consist of 32 or 64 hex digits starting with an optional '0x'. The I parameter indicates which block chaining mode is to be used. Currently aes-cbc (aes-128-cbc) and aes-256-cbc are supported. The encrypted data is integrity protected using encrypt-then-mac. The I parameter will attempt to remove the given keyfile once the key has been read. =item B<--migration-key pwdfile=Epassphrase fileE|pwdfd=EfdE [,mode=aes-cbc|aes-256-cbc][,remove[=true|false]][,pdf=sha512|pbkdf2]> This variant of the key parameter allows a user to provide a passphrase in a file. The file is read and a key is derived from it using either a SHA512 hash or PBKDF2. By default PBKDF2 is used. =item B<--pid file=EpidfileE|fd=EfiledescriptorE> This options allows a user to set the name of file where the process ID (pid) of the TPM will be written into. It is also possible to pass a file descriptor to a file that has been opened for writing. =item B<-r|--runas EownerE> Switch to the given user. This option can only be used when swtpm is started as root. =item B<--seccomp action=none|log|kill> (since v0.2) This option allows a user to select the action to take by the seccomp profile when a syscall is executed that is not allowed. The default is I. To disable the seccomp profile, choose I. The I action logs offending syscalls. The I action is only available if libseccomp supports logging. This option is only available on Linux and only if swtpm was compiled with libseccomp support. =item B<--flags [not-need-init] [,startup-clear|startup-state|startup-deactivated|startup-none]> The I flag enables the TPM to accept TPM commands right after start without requiring an INIT to be sent to it through the command channel (see the '-i' option of swtpm_ioctl). The I options cause a TPM_Startup or TPM2_Startup command to automatically be sent. The I option is only valid for a TPM 1.2. These options imply I, except for the I option, which results in no command being sent. If I<--vtpm-proxy> is used, I is automatically chosen but this can be changed with this option. =item B<--print-capabilities> (since v0.2) Print capabilities that were added to swtpm after version 0.1. The output may contain the following: { "type": "swtpm", "features": [ "cmdarg-seccomp", "cmdarg-key-fd", "cmdarg-pwd-fd", "tpm-send-command-header", "flags-opt-startup", "rsa-keysize-1024", "rsa-keysize-2048", "rsa-keysize-3072" ] } The meaning of the feature verbs is as follows: =over 4 =item B The I<--seccomp> option is supported. =item B The I<--key> option supports the I parameter. =item B The I<--key> option supports the I parameter. =item B The TPM 2 commands may be prefixed by a header that carries a 4-byte command, 1 byte for locality, and 4-byte TPM 2 command length indicator. The TPM 2 will respond by preprending a 4-byte response indicator and a 4-byte trailer. All data is sent in big endian format. =item B The I<--flags> option supports the I options. =item B The TPM 2 supports the shown RSA key sizes. If none of the rsa-keysize verbs is shown then only RSA 2048 bit keys are supported. =back =item B<-h|--help> Display usage info. =back =head1 SEE ALSO B, B swtpm-0.6.3/man/man8/swtpm_bios.pod000066400000000000000000000062571421141172300172100ustar00rootroot00000000000000=head1 NAME swtpm_bios - BIOS simulation tool for swtpm =head1 SYNOPSIS B =head1 DESCRIPTION B is a tool that can send the commands to the TPM (I program) that typically are used by the BIOS to initialize the TPM. The user can choose among several command line options to choose the state the TPM should be set to. This command requires the environment variable I to be set for communication via TCP. Otherwise it will use the device set in the environment variable I or fall back to use I to send the commands to. In TCP mode, the environment variable I is used to indicate the host to send the commands to. By default I is assumed. The default TCP port is 6545 unless the environment variable I indicates another port. In case of success 0 will be returned. In case a TPM error was encountered the return code will be 128. In case of communcation failure 255 is returned. In case the TPM needs to be reset to become activated, 129 will be returned. This command will send the following sequence of commands to the TPM. =over 4 =item B -- startup TPM =item B -- PhysicalPresenceCMDEnable =item B -- turn on physical presence =item B -- get permanent flags =item B -- enable the TPM =item B -- activate TPM =item B -- continue self test =item B -- PhysicalPresenceCMDEnable =item B -- turn off physical presence & lock it =back The following options are supported: =over 4 =item B<--tpm-device EdeviceE> Use the given device rather than the default /dev/tpm0. This option overrides the TPM_DEVICE environment variable. =item B<--tcp EserverE:EportE> Connect to the given server and port; if no server is given, 127.0.0.1 is used; if port is not given, the default port 6545 is used. =item B<--unix EpathE> Connect to the given UnixIO path. =item B<-tpm2> The device is a TPM 2. =item B<-c> Send TPM_Startup(ST_CLEAR) (default). This instructs the TPM to start with clear state. =item B<-s> Send TPM_Startup(ST_STATE). This instructs the TPM to start by restoring previously saved state. =item B<-d> Send TPM_Startup(ST_DEACTIVATED). This instructs the TPM to start in deactivated mode. This option has no effect on a TPM 2. =item B<-n> Don't send a TPM_Startup command. =item B<-o> Only send the startup command and nothing else. =item B<-ea> Make sure that the TPM is activated; if the TPM requires a reset, the program will exist and return a return code of 129. =item B<-cs> Send a TPM_ContinueSelfTest command to a TPM 1.2 and a TPM2_IncrementalSelfTest command to a TPM 2. =item B<-u> Give up physical presence on a TPM 1.2. In case of a TPM 2 set the platform hierarchy to a random password. =item B<-v> Display version and exit. =item B<-h> Display the help screen and exit. =back =head1 SEE ALSO =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm_cert.pod000066400000000000000000000107661421141172300172110ustar00rootroot00000000000000=head1 NAME swtpm_cert - Tool to create EK and platform certs for swtpm (1.2 & 2.0) =head1 SYNOPSIS B =head1 DESCRIPTION B is a local CA tool for creating X.509v3 certificates for the TPM's Endorsement Key. The reason for this specific tool is that it works without access to the Endorsement Key's private key. Typically tools require either a self-signed certificate request or access to the private key to issue a certificate. This tool works with only the public key part. The following options are supported: =over 4 =item B<--type {ek|platform}> The type of certificate to create; by default an EK certificate is created. =item B<--pubkey > The public key (EK) in PEM format. =item B<--modulus > The modulus of the public key as a string of hex digits. This option can be used in place of the --pubkey option. =item B<--ecc-x > The elliptic curve parameter x as string of hex digits. =item B<--ecc-y > The elliptic curve parameter y as string of hex digits. =item B<--ecc-curveid > The elliptic curve's id. secp256r1, secp384r1, and secp521r1 are supported. If this option is not given, secp256r1 is assumed. =item B<--exponent > The exponent of the public key. By default 0x10001 is assumed. =item B<--signkey > The key used for signing the certificate. The file must be in PEM format. =item B<--signkey-password > Optional password for the signing key. =item B<--signkey-pwd > This is an alternative option for passing the signing key password. The following formats are supported for I: - : direct password - pass: : direct password - file: : password in file - fd: : read password from file descriptor - env: : read password from env. variable All passwords read from files and file descriptors must be a maximum of 255 bytes (plus one byte for terminating NUL byte). =item B<--parentkey-password > Optional password for a parent key. In case a TPM key is used for signing this would be the password for the TPM's storage root key (SRK). =item B<--parentkey-pwd > This is an alternative option for passing the parentkey password. See the description above for supported I formats. =item B<--issuercert > The X.509 certificate of this signer that takes on the role of a local CA. =item B<--out-cert > The name of the file to write the X.509v3 certificate into. The output will be in PEM format. =item B<--serial > Optional 32bit serial number for the certificate. =item B<--days > The number of days the certificate is valid; by default it is valid for 365 days. =item B<--pem> Write the resulting certificate in PEM format; DER format is the default. =item B<--tpm-manufacturer > The name of the TPM manufacturer. =item B<--tpm-model > The TPM model (part number). =item B<--tpm-version > The TPM's firmware version. =item B<--platform-manufacturer > The name of the platform manufacturer. =item B<--platform-model > The platform model. =item B<--platform-version > The platform's version. =item B<--subject > Subject to for example provide the location of the TPM in the format of C=,ST=,L=. Note that the location must no contain any spaces. =item B<--tpm2> Issue TPM 2 compliant certificates. =item B<--allow-signing> Create an EK that can also be used for signing. Without this option, the EK can only be used for key encipherment. This option requires --tpm2. =item B<--decryption> If --allow-signing is passed and the EK should also be useable for key encipherment, this option must be passed. Otherwise key encipherment is the default. This option requires --tpm2. =item B<--print-capabilities> (since v0.3) Print capabilities that were added to swtpm_cert after version 0.2. The output may contain the following: { "type": "swtpm_cert", "features": [ "cmdarg-signkey-pwd", "cmdarg-parentkey-pwd" ] } The maining of the feature verbs is as follows: =over 4 =item B The I<--signkey-pwd> option is supported. =item B The I<--parentkey-pwd> option is supported. =back =item B<--help, -h> Display the help screen =back =head1 SEE ALSO =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm_cuse.pod000066400000000000000000000177231421141172300172130ustar00rootroot00000000000000=head1 NAME swtpm - TPM Emulator for TPM 1.2 and 2.0 with a CUSE interface only =head1 SYNOPSIS B =head1 DESCRIPTION B implements a TPM software emulator built on libtpms. It provides access to TPM functionality over a Linux CUSE (character device in user space) interface. The B command should be used for a graceful shutdown of the CUSE TPM. The following options are supported: =over 4 =item B<-h | --help> Display help screen. =item B<--tpmstate dir=EdirE> This parameter allows to set the directory where the TPM will store its persistent state to. If this parameter is not set, the environment variable I can be set instead. =item B<-n Edevice nameE | --name=Edevice nameE (mandatory)> The name of the character device to create. To create /dev/vtpm-200, the given device name must be vtpm-200. The character device will be created automatically and use unused major and minor numbers unless they are explicitly requested through options. =item B<-M EmajorE | --maj=EmajorE> The device major number to use; can be omitted. =item B<-m EminorE | --min=EminorE> The device minor number to use; can be omitted. =item B<--tpm2> Choose TPM 2 functionality; by default a TPM 1.2 is chosen. =item B<-r EuserE | --runas=EuserE> The user to switch to and drop privileges. =item B<--log fd=EfdE|file=EpathE[,level=EnE]>[,prefix=EprefixE][,truncate] Enable logging to a file given its file descriptor or its path. Use '-' for path to suppress the logging. The level parameter allows to choose the level of logging. Starting at log level 5, libtpms debug logging is activated. All logged lines will be prefixed with prefix. By default no prefix is prepended. If I is passed, the log file will be truncated. =item B<--locality [reject-locality-4][,allow-set-locality]> The I parameter will cause TPM error messages to be returned for requests to set the TPM into locality 4. The I parameter allows the swtpm to receive TPM/TPM2_SetLocality commands. This is parameter is useful if the Linux VTPM proxy driver access is enabled by file descriptor passing. This option is implied by the I<--vtpm-proxy> option and therefore need not be explicity set if this option is passed. In all other cases care should be taken as to who can send the TPM/TPM2_SetLocality command. =item B<--key file=EkeyfileE|fd=EfdE[,format=Ehex|binaryE][,mode=aes-cbc|aes-256-cbc][,remove[=true|false]]> Enable encryption of the state files of the TPM. The keyfile must contain an AES key of supported size; 128 bit (16 bytes) and 256 bit (32 bytes) keys are supported. The key may be in binary format, in which case the file size must be 16 or 32 bytes. If the key is in hex format (default), the key may consist of 32 or 64 hex digits starting with an optional '0x'. The I parameter indicates which block chaining mode is to be used. Currently aes-cbc (aes-128-cbc) and aes-256-cbc are supported. The encrypted data is integrity protected using encrypt-then-mac. The I parameter will attempt to remove the given keyfile once the key has been read. =item B<--key pwdfile=Epassphrase fileE|pwdfd=EfdE[,mode=aes-cbc|aes-256-cbc][,remove[=true|false]][,kdf=sha512|pbkdf2]> This variant of the key parameter allows to provide a passphrase in a file. The file is read and a key is derived from it using either a SHA512 hash or PBKDF2. By default PBKDF2 is used. =item B<--migration-key file=EkeyfileE|fd=EfdE[,format=Ehex|binaryE][,mode=aes-cbc|aes-256-cbc][,remove[=true|false]]> The availability of a migration key ensures that the state of the TPM will not be revealed in unencrypted form by the swtpm_cuse program when the TPM state blobs are retreived through the ioctl interface. The migration key is not used for encrypting TPM state written to files, this is what the --key parameter is used for. The migration key and the key used for encrypting the TPM state files may be the same. While the key for the TPM state files needs to stay with those files it encrypts, the migration key needs to stay with the TPM state blobs. If for example the state of the TPM is migrated between hosts in a data center, then the TPM migration key must be available at all the destinations, so in effect it may have to be a key shared across all machines in the datacenter. In contrast to that, the key used for encrypting the TPM state files can be different for each TPM and need only be available on the host where the TPM state resides. The migration key enables the encryption of the TPM state blobs. The keyfile must contain an AES key of supported size; 128 bit (16 bytes) and 256 bit (32 bytes) keys are supported. The key may be in binary format, in which case the file size must be 16 or 32 bytes. If the key is in hex format (default), the key may consist of 32 or 64 hex digits starting with an optional '0x'. The I parameter indicates which block chaining mode is to be used. Currently aes-cbc (aes-128-cbc) and aes-256-cbc are supported. The encrypted data is integrity protected using encrypt-then-mac. The I parameter will attempt to remove the given keyfile once the key has been read. =item B<--migration-key pwdfile=Epassphrase fileE|pwdfd=EfdE[,mode=aes-cbc|aes-256-cbc][,remove[=true|false]][,kdf=sha512|pbkdf2]> This variant of the key parameter allows to provide a passphrase in a file. The file is read and a key is derived from it using either a SHA512 hash or PBKDF2. By default PBKDF2 is used. =item B<--pid file=EpidfileE>|fd=EfiledescriptorE> This options allows to set the name of file where the process ID (pid) of the CUSE TPM will be written into. The file will be written by the root user. It is also possible to pass a file descriptor to a file that has been opened for writing. =item B<--seccomp action=none|log|kill> (since v0.2) This option allows to select the action to take by the seccomp profile when a syscall is executed that is not allowed. The default is I. To disable the seccomp profile, choose I. The I action logs offending syscalls. The I action is only available if libseccomp supports logging. This option is only available on Linux and only if swtpm was compiled with libseccomp support. =item B<--flags [not-need-init] [,startup-clear|startup-state|startup-deactivated|startup-none]> The I flag enables the TPM to accept TPM commands right after start without requiring an INIT to be sent to it through the command channel (see the '-i' option of swtpm_ioctl). The I options cause a TPM_Startup or TPM2_Startup command to automatically be sent. The I option is only valid for a TPM 1.2. These options imply I, except for the I option, which results in no command being sent. =item B<--print-capabilities> (since v0.2) Print capabilities that were added to swtpm after version 0.1. The output may contain the following: { "type": "swtpm", "features": [ "cmdarg-seccomp", "cmdarg-key-fd" ] } The meaning of the feature verbs is as follows: =over 4 =item B The I<--seccomp> option is supported. =item B The I<--key> option supports the I parameter. =back =back =head1 EXAMPLES To start the CUSE TPM and have it create the character device /dev/foo, use the following commands: =over 4 # ensure that previous swtpm_cuse using /dev/foo is gone swtpm_ioctl -s /dev/foo # Start the swtpm with TPM 2 functionality and make it accessible # through /dev/foo. Have the swtpm_cuse write the TPM's persistent # state into the given directory. export TPM_PATH=/tmp/foo mkdir -p $TPM_PATH swtpm_cuse -n foo --tpm2 # Send TPM_Init to the TPM; this is absolutely necessary swtpm_ioctl -i /dev/foo =back =head1 SEE ALSO B, B swtpm-0.6.3/man/man8/swtpm_ioctl.pod000066400000000000000000000103501421141172300173530ustar00rootroot00000000000000=head1 NAME swtpm_ioctl - Utility for sending control commands to swtpm =head1 SYNOPSIS BdeviceE>] =head1 DESCRIPTION B implements a client tool for controlling the I and I TPM software emulators, such as for example their initialization and shutdown. Once it has been initialized, TPM commands can be sent to it. Note: The environment variable SWTPM_IOCTL_BUFFERSIZE can be set to the size for the buffer for state blob transfer to use. If it is not set, the ioctl() interface is used for transferring the state. This environment variable is primarily used for testing purposes. The following commands are supported: =over 4 =item B<--tpm-device EdeviceE> Use the given device. The full path to the character device must be provided, such as for example /dev/vtpm-200. This option can be used instead of providing the device as the last parameter. =item B<--tcp EserverE:EportE> Connect to the given server and port; if no server is given, 127.0.0.1 is used; if port is not given, the default port 6545 is used. =item B<--unix EpathE> Connect to the given UnixIO path. =item B<-c> Get the capability flags indicating which commands are supported. =item B<-i> Send a hardware initialization signal to the swtpm_cuse/swtpm. Volatile state previously written by the TPM will be read and the file automatically delete. =item B<-s> Initiate a graceful shut down. =item B<--stop> Stop the swtpm_cuse/swtpm. This does not shut it down. The I<-i> command can again be sent to it. After a stop it is also possible to load TPM stateblobs into the TPM using the I<--load> command. =item B<-e> Get the tpmEstablished bit. =item B<-r locality> Reset the tpmEstablished bit using the given locality. Only localities 3 and 4 work. This operation will not permanently change the localty that was previously set using the I<-l> option. =item B<-l locality> Set the locality for the subsequent TPM commands. =item B<-v> Have the TPM write the volatile state to a file. Upon a TPM_Init (-i) the TPM state will be read and the TPM can then resume operation without further intialization. =item B<-C> Cancel an ongoing TPM command. =item B<-h data> Reset and extend PCR 17 with the hash of the given data. If data is the single character '-', then all data are read from stdin. =item B<--save ETPM state blob nameE EfilenameE > Save the TPM state blob into the given file. Valid TPM state blob names are 'permanent', 'volatile', and 'savestate'. Note that this command can be executed at any time. However, to retrieve the latest volatile state, the I<-v> command should have been run immediately before running this command. The savestate blob will only be returned if a TPM_SaveState command was executed in the TPM (TPM 1.2). =item B<--load ETPM state blob nameE EfilenameE> Load the given TPM state blob from the given file. Valid TPM state blob names are 'permanent', 'volatile', and 'savestate'. Note that this command can only be executed on a TPM that is shut down. To then start the TPM with the uploaded state, the I<-i> command must be issued. =item B<-g> Get configuration flags that for example indicate which keys (file encryption or migration key) are in use by the TPM. =item B<--info EflagE> Get information about the TPM implementation in JSON format. The flag I, which has the value 1, returns information about the specification the TPM implementation followed. The flag I, which has the value 2, returns information about the manufacturer, model, and version of the TPM. =back =head1 EXAMPLE Start swtpm on port 10000 for the control port and emulate a TPM 1.2: #> swtpm socket --tpmstate dir=/tmp/myvtpm1 --log level=4 --ctrl type=tcp,port=10000 --server type=tcp,port=10001 --flags not-need-init Get information about the TPM implementation in JSON: #> swtpm_ioctl --tcp :10000 --info 1 {"TPMSpecification":{"family":"1.2","level":2,"revision":116}} #> swtpm_ioctl --tcp :10000 --info 2 {"TPMAttributes":{"manufacturer":"id:00001014","version":"id:00740001","model":"swtpm"}} Shut down the swtpm #> swtpm_ioctl --tcp :10000 -s =head1 SEE ALSO B swtpm-0.6.3/man/man8/swtpm_setup.conf.pod000066400000000000000000000057111421141172300203320ustar00rootroot00000000000000=head1 NAME swtpm_setup.conf - Configuration file for swtpm_setup =head1 DESCRIPTION The file I contains configuration information for swtpm_setup. It must only contain one configuration keyword per line, followed by an equals sign (=) and then followed by appropriate configuration information. A comment at the end of the line may be introduced by a hash (#) sign. Users may write their own configuration into I<${XDG_CONFIG_HOME}/swtpm_setup.conf> or if XDG_CONFIG_HOME is not set it may be in I<${HOME}/.config/swtpm_setup.conf>. The following keywords are recognized: =over 4 =item B This keyword is to be followed by the name of an executable or executable script used for creating various TPM certificates. The tool will be called with the following options =over 4 =item B<--type type> This parameter indicates the type of certificate to create. The type parameter may be one of the following: I, or I =item B<--dir dir> This parameter indicates the directory into which the certificate is to be stored. It is expected that the EK certificate is stored in this directory under the name ek.cert and the platform certificate under the name platform.cert. =item B<--ek ek> This parameter indicates the modulus of the public key of the endorsement key (EK). The public key is provided as a sequence of ASCII hex digits. =item B<--vmid ID> This parameter indicates the ID of the VM for which to create the certificate. =item B<--logfile > The log file to log output to; by default logging goes to stdout and stderr on the console. =item B<--configfile > The configuration file to use. This file typically contains configuration information for the invoked program. If omitted, the program must use its default configuration file. =item B<--optsfile > The options file to use. This file typically contains options that the invoked program uses. If omitted, the program must use its default options file. =item B<--tpm-spec-family >, B<--tpm-spec-level >, B<--tpm-spec-revision > These 3 options describe the TPM specification that was followed for the implementation of the TPM and will be part of the EK certificate. =item B<--tpm2> This option is passed in case a TPM 2 compliant certificate needs to be created. =back =item B This keyword is to be followed by the name of a configuration file that will be passed to the invoked program using the --configfile option described above. If omitted, the invoked program will use the default configuration file. =item B This keyword is to be followed by the name of an options file that will be passed to the invoked program using the --optsfile option described above. If omitted, the invoked program will use the default options file. =back =head1 SEE ALSO B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm_setup.pod000066400000000000000000000213151421141172300174040ustar00rootroot00000000000000=head1 NAME swtpm_setup - Swtpm tool to simulate the manufacturing of a TPM 1.2 or 2.0 =head1 SYNOPSIS B =head1 DESCRIPTION B is a tool that prepares the initial state for a libtpms-based TPM. The following options are supported: =over 4 =item B<--runas > Use this userid to run swtpm_setup.sh as. Only 'root' can use this option. =item B<--config > Path to configuration file containing the tool to use for creating certificates; see also B If this parameter is not provided, the default configuration file will be used. The search order for the default configuration file is as follows. If the environment variable XDG_CONFIG_HOME is set, ${XDG_CONFIG_HOME}/swtpm_setup.conf will be used if available, otherwise if the environment variable HOME is set, ${HOME}/.config/swtpm_setup.conf will be used if available. If none of the previous ones are available, /etc/swtpm_setup.conf will be used. =item B<--tpm-state > or B<--tpmstate > Path to a directory where the TPM's state will be written into; this is a mandatory argument =item B<--tpm > Path to the TPM executable; this is an optional argument and by default the swtpm executable found in the PATH will be used. =item B<--tpm2> Do setup on a TPM 2; by default a TPM 1.2 is setup. =item B<--createek> Create an endorsement key (EK). =item B<--allow-signing> Create an EK that can sign. This option requires --tpm2. This option will create a non-standard EK. When re-creating the EK, TPM 2 tools have to use the EK Template that is witten at an NV index corresponding to the created EK (e.g., NV index 0x01c00004 for RS 2048 EK). Otherwise the tool-created EK will not correspond to the actual key being used or the modulus shown in the EK certificate. Note that the TCG specification "EK Credential Profile For TPM Family 2.0; Level 0" suggests in its section on "EK Usage" that "the Endorsement Key can be a created as a decryption or signing key." However, some platforms will not accept an EK as a signing key, or as a signing and encryption key, and therefore this option should be used very carefully. =item B<--decryption> Create an EK that can be used for key encipherment. This is the default unless --allow-signing is passed. This option requires --tpm2. =item B<--ecc> Create elliptic curve crypto (ECC) keys; by default RSA keys are generated. =item B<--take-ownership> Take ownership; this option implies --createek. This option is only available for TPM 1.2. =item B<--ownerpass > Provide custom owner password; default is 'ooo'. This option is only available for TPM 1.2. =item B<--owner-well-known> Use a password of all zeros (20 bytes of zeros) as the owner password. This option is only available for TPM 1.2. =item B<--srkpass > Provide custom SRK password; default is 'sss'. This option is only available for TPM 1.2. =item B<--srk-well-known> Use a password of all zeros (20 bytes of zeros) as the SRK password. This option is only available for TPM 1.2. =item B<--create-ek-cert> Create an EK certificate; this implies --createek. =item B<--create-platform-cert> Create a platform certificate; this implies --create-ek-cert. =item B<--lock-nvram> Lock NVRAM access to all NVRAM locations that were written to. =item B<--display> At the end display as much info as possible about the configuration of the TPM. =item B<--logfile > The logfile to log to. By default logging goes to stdout and stderr. =item B<--keyfile > The key file contains an ASCII hex key consisting of 32 hex digits with an optional leading '0x'. This is the key to be used by the TPM emulator for encrypting the state of the TPM. =item B<--keyfile-fd > Like B<--keyfile> but the key will be read from the file descriptor. =item B<--pwdfile > The passphrase file contains a passphrase from which the TPM emulator will derive the encryption key from and use the key for encrypting the TPM state. =item B<--pwdfile-fd > Like B<--pwdfile> but the passphrase will be read from the file descriptor. =item B<--ciper > The cipher may be either aes-cbc or aes-128-cbc for 128 bit AES encryption, or aes-256-cbc for 256 bit AES encryption. The same cipher must be used on the I command line later on. =item B<--overwrite> Overwrite existing TPM state. All previous state will be erased. If this option is not given and an existing state file is found, an error code is returned. =item B<--not-overwrite> Do not overwrite existing TPM state. If existing TPM state is found, the program ends without an error. =item B<--vmid > Optional VM ID that can be used to keep track of certificates issued for VMs (or containers). This parameter will be passed through to the tool used for creating the certificates and may be required by that tool. =item B<--pcr-banks > Optional comma-separated list of PCR banks to activate. Providing '-' allows a user to skip the selection and activates all PCR banks. By default the sha1 and sha256 banks are activated. =item B<--swtpm_ioctl > Pass the path to the swtpm_ioctl executable. By default the swtpm_ioctl in the PATH is used. =item B<--tcsd-system-ps-file > This option is deprecated and has no effect (since v0.4). =item B<--rsa-keysize > (since v0.4) This option allows to pass the size of a TPM 2 RSA EK key, such as 2048 or 3072. The supported keysizes for a TPM 2 can be queried for using the I<--print-capabilities> option. The default size is 2048 bits for both TPM 1.2 and TPM 2. If 'max' is passed, the largest possible key size is used. =item B<--print-capabilities> (since v0.2) Print capabilities that were added to swtpm_setup after version 0.1. The output may contain the following: { "type": "swtpm_setup", "features": [ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm2-rsa-keysize-2048", "tpm2-rsa-keysize-3072", "tpm12-not-need-root" ] } The meaning of the feature verbs is as follows: =over 4 =item B The I<--keyfile-fd> option is supported. =item B The I<--pwdfile-fd> option is supported. =item B The shown RSA key sizes are supported for a TPM 2's EK key. If none of the tpm2-rsa-keysize verbs is shown then only RSA 2048 bit keys are supported. =item B (since 0.4.0) This option implies that any user can setup a TPM 1.2. Previously only root or the 'tss' user, depending on configuration and availability of this account, could do that. =back =item B<--help, -h> Display the help screen =back =head1 EXAMPLE USAGE To simulate manufacturing of a TPM, one would typically run the following command: #> sudo swtpm_setup --tpmstate /tmp/mytpm1/ \ --create-ek-cert --create-platform-cert --lock-nvram Note: since v0.4 TPM 1.2 setup does not require root rights anymore. Any user can also simulate the manufacturing of a TPM using the swtpm-localca plugin. The following example assumes that the user has set the environment variable XDG_CONFIG_HOME as follows (using bash for example): export XDG_CONFIG_HOME=~/.config Note: The XDG_CONFIG_HOME variable is part of the XDG Base Directory Specification. The following configuration files need to be created: ~/.config/swtpm_setup.conf: # Program invoked for creating certificates create_certs_tool= /usr/share/swtpm/swtpm-localca create_certs_tool_config = ${XDG_CONFIG_HOME}/swtpm-localca.conf create_certs_tool_options = ${XDG_CONFIG_HOME}/swtpm-localca.options ~/.config/swtpm-localca.conf: statedir = ${XDG_CONFIG_HOME}/var/lib/swtpm-localca signingkey = ${XDG_CONFIG_HOME}/var/lib/swtpm-localca/signkey.pem issuercert = ${XDG_CONFIG_HOME}/var/lib/swtpm-localca/issuercert.pem certserial = ${XDG_CONFIG_HOME}/var/lib/swtpm-localca/certserial ~/.config/swtpm-localca.options: --platform-manufacturer Fedora --platform-version 2.12 --platform-model QEMU Note: The tool swtpm-create-user-config-files can be used to create such files (with different content): #> /usr/share/swtpm/swtpm-create-user-config-files Writing /home/stefanb/.config/swtpm_setup.conf. Writing /home/stefanb/.config/swtpm-localca.conf. Writing /home/stefanb/.config/swtpm-localca.options. The following commands now create a TPM 2 with an EK and platform certificate. The state of the TPM 2 will be stored in the directory ${XDG_CONFIG_HOME}/mytpm1. #> mkdir -p ${XDG_CONFIG_HOME}/mytpm1 #> swtpm_setup --tpm2 --tpmstate ${XDG_CONFIG_HOME}/mytpm1 \ --create-ek-cert --create-platform-cert --lock-nvram =head1 SEE ALSO B =head1 REPORTING BUGS Report bugs to Stefan Berger swtpm-0.6.3/man/man8/swtpm_setup.sh.8000066400000000000000000000000271421141172300173770ustar00rootroot00000000000000.so man8/swtpm_setup.8 swtpm-0.6.3/run_tests000077500000000000000000000026211421141172300146430ustar00rootroot00000000000000#!/bin/bash if [ $(uname -p) != "x86_64" ]; then echo "This test only runs on x86_64 host" exit 1 fi unset SWTPM # Comment the following to compile and test with CUSE interface WITHOUT_CUSE="--without-cuse" # FIXME: # Due to some bug in glib2 for i686 we don't seem to be able to run a # 32bit swtpm with cuse interface correctly. The g_cond_wait_until() # doesn't behave as it does with 64bit. test_hashing2 gets stuck. CFLAGS='-m64' ./configure --with-openssl --with-gnutls --prefix=/usr --libdir=/lib64 ${WITHOUT_CUSE} && \ make clean && \ make -j$(nproc) && sudo make -j$(nproc) install && cp /usr/bin/swtpm /tmp/swtpm64 && make -j$(nproc) check || exit 1 if [ -z "${WITHOUT_CUSE}" ]; then sudo make -j$(nproc) check || exit 1 fi PKG_CONFIG_PATH=/usr/lib/pkgconfig \ CFLAGS='-m32' ./configure --with-openssl --with-gnutls --prefix=/usr --libdir=/lib ${WITHOUT_CUSE} && \ make clean && \ make -j$(nproc) && sudo make -j$(nproc) install && cp /usr/bin/swtpm /tmp/swtpm32 && make -j$(nproc) check && SWTPM_EXE=/tmp/swtpm64 make -j$(nproc) check || exit 1 if [ -z "${WITHOUT_CUSE}" ]; then sudo SWTPM_EXE=/tmp/swtpm64 make -j$(nproc) check || exit 1 fi CFLAGS='-m64' ./configure --with-openssl --with-gnutls --prefix=/usr --libdir=/lib64 ${WITHOUT_CUSE} && \ make clean && \ make -j$(nproc) && SWTPM_EXE=/tmp/swtpm32 make -j$(nproc) check || exit 1 echo "*** All tests succeeded ***" exit 0 swtpm-0.6.3/samples/000077500000000000000000000000001421141172300143325ustar00rootroot00000000000000swtpm-0.6.3/samples/Makefile.am000066400000000000000000000025321421141172300163700ustar00rootroot00000000000000# # samples/Makefile.am # # For the license, see the LICENSE file in the root directory. # samplesconfdir = $(datadir)/@PACKAGE@ samplessysconfdir = $(sysconfdir) # swtpm-localca was always installed in /usr/samples/swtpm-localca bindir = $(samplesconfdir) samplesconf_SCRIPTS = \ swtpm-create-tpmca \ swtpm-create-user-config-files samplessysconf_DATA = \ swtpm-localca.conf \ swtpm-localca.options noinst_HEADERS = \ swtpm_localca.h \ swtpm_localca_utils.h bin_PROGRAMS = \ swtpm-localca $(top_builddir)/src/utils/libswtpm_utils.la: $(MAKE) -C$(dir $@) swtpm_localca_DEPENDENCIES = \ $(top_builddir)/src/utils/libswtpm_utils.la swtpm_localca_SOURCES = \ swtpm_localca.c \ swtpm_localca_utils.c swtpm_localca_LDADD = \ $(top_builddir)/src/utils/libswtpm_utils.la swtpm_localca_LDFLAGS = \ -L$(top_builddir)/src/utils -lswtpm_utils \ $(HARDENING_LDFLAGS) \ $(GLIB_LIBS) swtpm_localca_CFLAGS = \ -I$(top_srcdir)/src/utils \ $(HARDENING_CFLAGS) \ $(GLIB_CFLAGS) install-data-local: $(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/swtpm-localca if test -z $(DESTDIR); then \ chown -R @TSS_USER@:root $(DESTDIR)$(localstatedir)/lib/swtpm-localca || true; \ chmod 0750 $(DESTDIR)$(localstatedir)/lib/swtpm-localca || true; \ fi EXTRA_DIST= \ swtpm-create-tpmca \ swtpm-create-user-config-files \ swtpm-localca.conf \ swtpm-localca.options swtpm-0.6.3/samples/swtpm-create-tpmca000077500000000000000000000321521421141172300200000ustar00rootroot00000000000000#!/usr/bin/env bash FLAG_OVERWRITE=1 FLAG_REGISTER_KEY=2 FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN=4 FLAG_SRK_WELL_KNOWN=8 FLAG_TPM2=16 TSS_TCSD_HOSTNAME_DEFAULT=localhost TSS_TCSD_PORT_DEFAULT=30003 logit() { if [ -z "$LOGFILE" ]; then echo "$@" >&1 else echo "$@" >> "$LOGFILE" fi } logerr() { if [ -z "$LOGFILE" ]; then echo "Error: $*" >&2 else echo "Error: $*" >> "$LOGFILE" fi } # Get the size of a file in bytes # # @1: filename function get_filesize() { if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then stat -c%s "$1" else # OpenBSD stat -f%z "$1" fi } # Create a config value by escaping the proper characters # # @param 1: The string to escape function escape_pkcs11_url() { echo "$1" | sed 's/;/\\;/g' } # Use expect for automating the interaction with the tpmtool # # @param 1...: parameters to pass to tpmtool command line # # TPM_SRK_PASSWORD and TPM_KEY_PASSWORD global variables are used # for the SRK and key passwords respectively. run_tpmtool() { local prg out rc prg="spawn tpmtool "$@" expect { \"Enter SRK password:\" { send \"${TPM_SRK_PASSWORD}\n\" exp_continue } \"Enter key password:\" { send \"${TPM_KEY_PASSWORD}\n\" exp_continue } \"tpmkey:\" { send_user \"\n\" } eof { exit } } catch wait result exit [lindex \$result 3] " out=$(expect -c "${prg}") rc=$? echo "${out}" return $rc } #run_tpmtool create_localca_cert() { local flags=$1 local dir="$2" local outfile="$3" local owner="$4" local pid="$5" # TPM2 parameter local cakey=${dir}/swtpm-localca-rootca-privkey.pem local cacert=${dir}/swtpm-localca-rootca-cert.pem local tpmkey=${dir}/swtpm-localca-tpmca-privkey.pem local tpmpubkey=${dir}/swtpm-localca-tpmca-pubkey.pem local tpmca=${dir}/swtpm-localca-tpmca-cert.pem local template=${dir}/template local tpmkeyurl local msg output if ! [ -r "${cakey}" ] || ! [ -r "${cacert}" ]; then msg=$("${CERTTOOL}" \ --generate-privkey \ ${SWTPM_ROOTCA_PASSWORD:+--password "${SWTPM_ROOTCA_PASSWORD}"} \ --outfile "${cakey}" \ 2>&1) [ $? -ne 0 ] && { logerr "Could not create root-CA key ${cakey}." logerr "${msg}" return 1 } chmod 640 "${cakey}" echo "cn=swtpm-localca-rootca" > "${template}" echo "ca" >> "${template}" echo "cert_signing_key" >> "${template}" echo "expiration_days = 3650" >> "${template}" msg=$(GNUTLS_PIN="${SWTPM_ROOTCA_PASSWORD}" ${CERTTOOL} \ --generate-self-signed \ --template "${template}" \ --outfile "${cacert}" \ --load-privkey "${cakey}" \ 2>&1) if [ $? -ne 0 ]; then logerr "Could not create root CA." logerr "${msg}" rm -f "${cakey}" "${template}" return 1 fi else logit "Reusing existing root CA" fi rm -f "${tpmkey}" "${tpmpubkey}" "${tpmca}" if [ $((flags & FLAG_TPM2)) -ne 0 ]; then local tokenurl tpmkeyurl local token="swtpm-tpmca-${pid}" local label="${token}" # must be same local keylabel="swtpm-tpmca-key" local userpin="${SWTPM_PKCS11_PIN:-swtpm-tpmca}" tokenurl=$(p11tool --list-tokens 2>&1 | \ grep -E ";token=${token}\$" | \ sed -n "s/.*URL: //p") if [ -z "${tokenurl}" ]; then if [ -z "${SWTPM_PKCS11_SO_PIN}" ]; then logerr "The env. variable SWTPM_PKCS11_SO_PIN must be set to create token ${label}." return 1 fi msg=$(tpm2_ptool addtoken \ --pid "${pid}" \ --sopin "${SWTPM_PKCS11_SO_PIN}" \ --userpin "${userpin}" \ --label "${label}" 2>&1) if [ $? -ne 0 ]; then logerr "Error: Could not create pkcs11 token" logerr "${msg}" return 1 fi tokenurl=$(p11tool --list-tokens 2>&1 | \ grep -E ";token=${token}\$" | \ sed -n "s/.*URL: //p") if [ -z "${tokenurl}" ]; then logerr "Error: Could not get token URL for token '${token}'" logerr "${msg}" return 1 fi msg=$(tpm2_ptool config \ --key tcti \ --value tabrmd \ --label "${label}") if [ $? -ne 0 ]; then logerr "Error: Could not set config value for tcti key" logerr "${msg}" return 1 fi fi export GNUTLS_PIN="${userpin}" # GNUTLS_SO_PIN not needed at this point msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)" if [ $? -eq 0 ]; then tpmkeyurl=$(echo "${msg}" | \ grep ";object=${keylabel}" | \ sed -n "s/.*URL: //p") fi if [ -z "${tpmkeyurl}" ]; then msg=$(tpm2_ptool addkey \ "--label=${label}" \ "--userpin=${userpin}" \ --algorithm=rsa2048 \ "--key-label=${keylabel}" \ --id 1 2>&1) if [ $? -ne 0 ]; then logerr "Error: Could not create create key under pkcs11 token ${token}" logerr "${msg}" return 1 fi msg="$(p11tool --login --list-keys "${tokenurl}" 2>&1)" if [ $? -ne 0 ]; then logerr "Error: Could not get TPM key URL for ${tokenurl}" logerr "${msg}" return 1 fi tpmkeyurl=$(echo "${msg}" | \ grep ";object=${keylabel}" | \ sed -n "s/.*URL: //p") if [ -z "${tpmkeyurl}" ]; then logerr "Error: Could not get TPM key URL for ${tokenurl}" logerr "${msg}" return 1 fi fi rm -f "${tpmpubkey}" msg=$(p11tool --export-pubkey "${tpmkeyurl}" --login --outfile "${tpmpubkey}" 2>&1) if [ $? -ne 0 ] || \ [ ! -r "${tpmpubkey}" ] || [ $(get_filesize "${tpmpubkey}") -eq 0 ]; then logerr "Error: Could not get TPM public key" logerr "${msg}" rm -f "${tpmkey}" "${tpmpubkey}" return 1 fi else local params="" if [ $((flags & FLAG_SRK_WELL_KNOWN)) -ne 0 ]; then unset GNUTLS_PIN params="--srk-well-known" else export GNUTLS_PIN="${TPM_SRK_PASSWORD}" fi if [ $((flags & FLAG_REGISTER_KEY)) -ne 0 ]; then msg="$(run_tpmtool --generate-rsa --signing --register ${params})" if [ $? -ne 0 ]; then logerr "Could not generate registered signing key with tpmtool" logerr "${msg}" return 1 fi tpmkeyurl=$(echo "${msg}" | sed -n 's/\(tpmkey:uuid=[^;]*\);.*/\1/p') if [ -z "${tpmkeyurl}" ]; then logerr "Could not parse tpmkey URL" logerr "${msg}" return 1 fi else rm -f "${tpmkey}" msg="$(run_tpmtool --generate-rsa --signing --outfile \"${tpmkey}\" ${params})" if [ $? -ne 0 ]; then logerr "Could not create signing key with tpmtool" logerr "${msg}" rm -f "${tpmkey}" return 1 fi if [ ! -r "${tpmkey}" ] || [ $(get_filesize "${tpmkey}") -eq 0 ]; then logerr "The TPM key file ${tpmkey} was not written properly" logerr "${msg}" rm -f "${tpmkey}" return 1 fi chmod 640 "${tpmkey}" tpmkeyurl="tpmkey:file=${tpmkey}" fi rm -f "${tpmpubkey}" msg=$(run_tpmtool "--pubkey=${tpmkeyurl}" --outfile \"${tpmpubkey}\" ${params}) if [ $? -ne 0 ] || \ [ ! -r "${tpmpubkey}" ] || [ $(get_filesize "${tpmpubkey}") -eq 0 ]; then logerr "Error: Could not get TPM public key" logerr "${msg}" rm -f "${tpmkey}" "${tpmpubkey}" return 1 fi fi echo "cn=swtpm-localca" > "${template}" echo "ca" >> "${template}" echo "cert_signing_key" >> "${template}" echo "expiration_days = 3650" >> "${template}" msg=$(${CERTTOOL} \ --generate-certificate \ --template "${template}" \ --outfile "${tpmca}" \ --load-ca-privkey "${cakey}" \ --load-ca-certificate "${cacert}" \ --load-privkey "${tpmkeyurl}" \ --load-pubkey "${tpmpubkey}" \ 2>&1) if [ $? -ne 0 ]; then logerr "Could not create TPM CA" logerr "${msg}" rm -f "${template}" return 1 fi output="statedir = ${dir} signingkey = $(escape_pkcs11_url ${tpmkeyurl}) issuercert = ${tpmca} certserial = ${dir}/certserial" if [ $((flags & FLAG_TPM2)) -eq 0 ]; then output+="$(echo -e "\nTSS_TCSD_HOSTNAME = ${TSS_TCSD_HOSTNAME}")" output+="$(echo -e "\nTSS_TCSD_PORT = ${TSS_TCSD_PORT}")" else output+="$(echo -e "\nSWTPM_PKCS11_PIN = ${SWTPM_PKCS11_PIN}")" # output+="$(echo -e "\nSWTPM_PKCS11_SO_PIN = ${SWTPM_PKCS11_SO_PIN}")" fi if [ -n "${TPM_KEY_PASSWORD}" ]; then output+="$(echo -e "\nsigningkey_password = ${TPM_KEY_PASSWORD}")" fi if [ -n "${TPM_SRK_PASSWORD}" ]; then output+="$(echo -e "\nparentkey_password = ${TPM_SRK_PASSWORD}")" fi if [ -n "${outfile}" ]; then echo "${output}" > "${outfile}" chmod 640 "${outfile}" fi echo "${output}" if [ "$(id -u)" -eq 0 ]; then chown "${owner}:${group}" "${dir}" pushd "${dir}" &>/dev/null if [ $? -eq 0 ]; then chown "${owner}:${group}" ./* popd &>/dev/null fi if [ -n "${outfile}" ]; then chown "${owner}:${group}" "${outfile}" fi fi rm -f "${template}" return 0 } #create_localca_cert usage() { local flags=$2 local tpmtool_note=" use 'well known' password if not given" [ $((flags & FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN)) -eq 0 ] && \ tpmtool_note=" Note: the well known password of 20 zero bytes is not supported by tpmtool" cat << _EOF_ Create a TPM-based CA for signing EK and platform certificates. Usage: $(basename "$1") [options] THIS SCRIPT IS EXPERIMENTAL The following options are supported: --dir directory Directory where to write the CA files into; must not exist unless --overwrite is passed --overwrite Overwrite any data in an existing directory; tries to reuse a root CA if one is found there --register Create a registered TPM 1.2 key rather than a file that contains the key; this option has no effect if --tpm2 is used --key-password s Password for the newly created TPM key; required if --register is not passed Note: use the same as the --srk-password (bug in certtool) --srk-password s Password for the TPM's SRK;${tpmtool_note} --outfile file File to write the configuration to; if not passed it will be written to stdout only --owner owner The owner of the directory and the files; only set if this script is run as root; recommended to be 'tss' --group group The group owning the directory and the files; recommended to be 'tss' --tss-tcsd-hostname hostname The name of the host where tcsd (TrouSerS daemon) is running on; default is '${TSS_TCSD_HOSTNAME_DEFAULT}' --tss-tcsd-port p The TCP port on which tcsd is listening for connections; default is ${TSS_TCSD_PORT_DEFAULT} --tpm2 Setup a CA that uses a TPM 2.0 --pid Pimary object Id used by tpm2_ptool; only valid if --tpm2 is used --help, -h, -? Display this help screen and exit The following environment variables are supported: SWTPM_ROOTCA_PASSWORD The root CA's private key password _EOF_ } #usage # Check whether tpmtool supports --srk-well-known tpmtool_supports_srk_well_known() { local tmp tmp=$(tpmtool --help | grep "srk-well-known") [ -z "${tmp}" ] && return 1 return 0 } main() { local flags=0 local dir outfile owner group msg pid if tpmtool_supports_srk_well_known; then flags=$((flags | FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN | FLAG_SRK_WELL_KNOWN)) fi CERTTOOL=certtool export TSS_TCSD_HOSTNAME=${TSS_TCSD_HOSTNAME_DEFAULT} export TSS_TCSD_PORT=${TSS_TCSD_PORT_DEFAULT} while [ $# -ne 0 ]; do case "$1" in --dir) shift dir="$1" ;; --overwrite) flags=$((flags | FLAG_OVERWRITE)) ;; --register) flags=$((flags | FLAG_REGISTER_KEY)) ;; --srk-password) shift TPM_SRK_PASSWORD="$1" flags=$((flags & ~FLAG_SRK_WELL_KNOWN)) ;; --key-password) shift TPM_KEY_PASSWORD="$1" ;; --outfile) shift outfile="$1" ;; --owner) shift owner="$1" ;; --group) shift group="$1" ;; --tss-tcsd-hostname) shift TSS_TCSD_HOSTNAME="$1" ;; --tss-tcsd-port) shift TSS_TCSD_PORT="$1" ;; --tpm2) flags=$((flags | FLAG_TPM2)) ;; --pid) shift pid="$1" ;; --help|-h|-?) usage "$0" "${flags}" exit 0 ;; *) logerr "Unsupported option $1" exit 1 ;; esac shift done if [ -z "${dir}" ]; then logerr "Missing --dir option." return 1 fi # strip trailing '/' from dir dir="$(echo "${dir}" | sed -n 's|[/]*$||p')" if [ -d "${dir}" ] && [ $((flags & FLAG_OVERWRITE)) -eq 0 ]; then logerr "Refusing to overwrite existing directory ${dir}." return 1 fi if [ -z "${TPM_SRK_PASSWORD}" ] && [ $((flags & FLAG_TPM2)) -eq 0 ] && [ $((flags & FLAG_TPMTOOL_SUPPORTS_SRK_WELL_KNOWN)) -eq 0 ]; then logerr "SRK password must be provided" return 1 fi if [ -z "${TPM_KEY_PASSWORD}" ] && \ [ $((flags & FLAG_REGISTER_KEY)) -eq 0 ] && \ [ $((flags & FLAG_TPM2)) -eq 0 ]; then logerr "Key password is required" return 1 fi if [ $((flags & FLAG_TPM2)) -ne 0 ] && [ -z "${pid}" ]; then logerr "--pid is required for TPM 2" return 1 fi if [ "$(id -u)" -eq 0 ]; then if [ -n "${owner}" ]; then msg="$(id -u "${owner}" 2>&1)" if [ $? -ne 0 ]; then logerr "User ${owner} cannot be used: ${msg}" return 1 fi else owner="root" fi if [ -n "${group}" ]; then msg="$(id -g "${group}" 2>&1)" if [ $? -ne 0 ]; then logerr "Group ${group} cannot be used: ${msg}" return 1 fi else group="root" fi fi mkdir -p "${dir}" if [ $? -ne 0 ]; then logerr "Could not create directory ${dir}." return 1 fi create_localca_cert "${flags}" "${dir}" "${outfile}" "${owner}" "${pid}" return $? } #main main "$@" exit $?swtpm-0.6.3/samples/swtpm-create-user-config-files.in000077500000000000000000000044531421141172300226250ustar00rootroot00000000000000#!/usr/bin/env bash if [ -z "${XDG_CONFIG_HOME}" ]; then echo "Environment variable XDG_CONFIG_HOME is not set. Using \${HOME}/.config." XDG_CONFIG_HOME="${HOME}/.config" fi SWTPM_LOCALCA_DIR="${XDG_CONFIG_HOME}/var/lib/swtpm-localca" SWTPM_SETUP_CONF="${XDG_CONFIG_HOME}/swtpm_setup.conf" SWTPM_LOCALCA_CONF="${XDG_CONFIG_HOME}/swtpm-localca.conf" SWTPM_LOCALCA_OPTIONS="${XDG_CONFIG_HOME}/swtpm-localca.options" FLAG_OVERWRITE=1 FLAG_ROOT=2 function help() { cat <<_EOF_ Usage: $1 [options] The following options are supported: --overwrite : Overwrite existing config files --root : Allow the installation of the config files under the root account. This will shadow the default configuration files under @SYSCONFDIR@. --help|-h|-? : Display this help screen and exit _EOF_ } function main() { local flags=0 while [ $# -ne 0 ]; do case "$1" in --overwrite) flags=$((flags | FLAG_OVERWRITE));; --root) flags=$((flags | FLAG_ROOT));; --help|-h|-?) help $0; exit 0;; *) echo -e "Unknown option $1\n" >&2; help $0; exit 1;; esac shift done if [ "$(id -u)" = "0" ]; then if [[ $((flags & FLAG_ROOT)) -eq 0 ]]; then echo "Requiring the --root flag since the configuration files will shadow" echo "those in @SYSCONFDIR@." exit 1 fi fi if [[ $((flags & FLAG_OVERWRITE)) -eq 0 ]]; then for f in "${SWTPM_SETUP_CONF}" \ "${SWTPM_LOCALCA_CONF}" \ "${SWTPM_LOCALCA_OPTIONS}"; do if [ -f "${f}" ]; then echo "File ${f} already exists. Refusing to overwrite." >&2 exit 1 fi done fi mkdir -p "${SWTPM_LOCALCA_DIR}" echo "Writing ${SWTPM_SETUP_CONF}." cat <<_EOF_ > "${SWTPM_SETUP_CONF}" create_certs_tool = @DATAROOTDIR@/swtpm/swtpm-localca create_certs_tool_config = ${SWTPM_LOCALCA_CONF} create_certs_tool_options = ${SWTPM_LOCALCA_OPTIONS} _EOF_ echo "Writing ${SWTPM_LOCALCA_CONF}." cat <<_EOF_ > "${SWTPM_LOCALCA_CONF}" statedir = ${SWTPM_LOCALCA_DIR} signingkey = ${SWTPM_LOCALCA_DIR}/signkey.pem issuercert = ${SWTPM_LOCALCA_DIR}/issuercert.pem certserial = ${SWTPM_LOCALCA_DIR}/certserial _EOF_ echo "Writing ${SWTPM_LOCALCA_OPTIONS}." cat <<_EOF_ > "${SWTPM_LOCALCA_OPTIONS}" --platform-manufacturer $(uname -s | tr " " "_") --platform-version $(uname -r | tr " " "_") --platform-model $(uname -s | tr " " "_") _EOF_ exit 0 } main "$@" swtpm-0.6.3/samples/swtpm-localca.conf.in000066400000000000000000000003401421141172300203510ustar00rootroot00000000000000statedir = @LOCALSTATEDIR@/lib/swtpm-localca signingkey = @LOCALSTATEDIR@/lib/swtpm-localca/signkey.pem issuercert = @LOCALSTATEDIR@/lib/swtpm-localca/issuercert.pem certserial = @LOCALSTATEDIR@/lib/swtpm-localca/certserial swtpm-0.6.3/samples/swtpm-localca.options000066400000000000000000000001141421141172300205110ustar00rootroot00000000000000--platform-manufacturer Fedora --platform-version 2.1 --platform-model QEMU swtpm-0.6.3/samples/swtpm_localca.c000066400000000000000000001001331421141172300173240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_localca.c: A tool for creating TPM 1.2 and TPM 2 certificates localy or using pkcs11 * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swtpm_utils.h" #include "swtpm_localca_conf.h" #include "swtpm_localca_utils.h" #define SETUP_TPM2_F 1 /* for TPM 2 EK */ #define ALLOW_SIGNING_F 2 #define DECRYPTION_F 4 /* Default logging goes to stderr */ gchar *gl_LOGFILE = NULL; #define LOCALCA_OPTIONS "swtpm-localca.options" #define LOCALCA_CONFIG "swtpm-localca.conf" #if defined __APPLE__ # define CERTTOOL_NAME "gnutls-certtool" #else # define CERTTOOL_NAME "certtool" #endif /* initialize the path of the options and config files */ static int init(gchar **options_file, gchar **config_file) { const char *xch = getenv("XDG_CONFIG_HOME"); const char *home = getenv("HOME"); char path[PATH_MAX]; const char *p = NULL; int ret = 0; if (xch != NULL && (p = pathjoin(path, sizeof(path), xch, LOCALCA_OPTIONS, NULL)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else if (home != NULL && (p = pathjoin(path, sizeof(path), home, ".config", LOCALCA_OPTIONS)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else { p = pathjoin(path, sizeof(path), G_DIR_SEPARATOR_S, SYSCONFDIR, LOCALCA_OPTIONS); } *options_file = g_strdup(p); if (xch != NULL && (p = pathjoin(path, sizeof(path), xch, LOCALCA_CONFIG, NULL)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else if (home != NULL && (p = pathjoin(path, sizeof(path), home, ".config", LOCALCA_CONFIG)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else { p = pathjoin(path, sizeof(path), G_DIR_SEPARATOR_S, SYSCONFDIR, LOCALCA_CONFIG); } *config_file = g_strdup(p); return ret; } /* Run the certtool command line prepared in cmd. Display error message * in case of failure and also display the keyfile if something goes wrong. */ static int run_certtool(gchar **cmd, gchar **env, const char *msg, gchar *keyfile) { g_autofree gchar *standard_error = NULL; gint exit_status; GError *error = NULL; gboolean success; success = g_spawn_sync(NULL, cmd, env, G_SPAWN_STDOUT_TO_DEV_NULL, NULL, NULL, NULL, &standard_error, &exit_status, &error); if (!success || exit_status != 0) { logerr(gl_LOGFILE, "%s" , msg); if (keyfile) logerr(gl_LOGFILE, " %s:", keyfile); if (!success) { logerr(gl_LOGFILE, "%s\n", error->message); g_error_free(error); } else { logerr(gl_LOGFILE, "%s\n", standard_error); } return 1; } return 0; } /* Create a root CA key and cert and a local CA key and cert. The latter will be * used for signing the TPM certs. */ static int create_localca_cert(const gchar *lockfile, const gchar *statedir, const gchar *signkey, const gchar *signkey_password, const gchar *issuercert) { int lockfd; int ret = 1; struct stat statbuf; int template1_file_fd = -1; int template2_file_fd = -1; g_autofree gchar *template1_file = NULL; g_autofree gchar *template2_file = NULL; gchar **certtool_env = NULL; lockfd = lock_file(lockfile); if (lockfd < 0) return 1; if (stat(statedir, &statbuf) != 0) { if (makedir(statedir, "statedir") != 0) goto error; } if (access(signkey, R_OK) != 0 || access(issuercert, R_OK) != 0) { g_autofree gchar *directory = g_path_get_dirname(signkey); g_autofree gchar *cakey = g_strjoin(G_DIR_SEPARATOR_S, directory, "swtpm-localca-rootca-privkey.pem", NULL); g_autofree gchar *cacert = g_strjoin(G_DIR_SEPARATOR_S, directory, "swtpm-localca-rootca-cert.pem", NULL); const gchar *swtpm_rootca_password = g_getenv("SWTPM_ROOTCA_PASSWORD"); g_autofree gchar *certtool = g_find_program_in_path(CERTTOOL_NAME); g_autofree gchar **cmd = NULL; g_autofree gchar *fc = NULL; const char *filecontent; if (certtool == NULL) { logerr(gl_LOGFILE, "Could not find %s in PATH.\n", CERTTOOL_NAME); goto error; } /* generate the root-CA's private key */ cmd = concat_arrays(cmd, (gchar*[]){ (gchar *)certtool, "--generate-privkey", "--outfile", cakey, NULL }, TRUE); if (swtpm_rootca_password != NULL) cmd = concat_arrays(cmd, (gchar*[]){ "--password", (gchar *)swtpm_rootca_password, NULL }, TRUE); if (run_certtool(cmd, certtool_env, "Could not create root-CA key", cakey)) goto error; if (chmod(cakey, S_IRUSR | S_IWUSR | S_IRGRP) != 0) { logerr(gl_LOGFILE, "Could not chmod %s: %s\n", cakey, strerror(errno)); goto error; } certtool_env = g_environ_setenv(NULL, "PATH", g_getenv("PATH"), TRUE); /* create the root-CA's cert */ filecontent = "cn=swtpm-localca-rootca\n" "ca\n" "cert_signing_key\n" "expiration_days = 3600\n"; template1_file_fd = write_to_tempfile(&template1_file, (const unsigned char *)filecontent, strlen(filecontent)); if (template1_file_fd < 0) goto error; g_free(cmd); cmd = concat_arrays(NULL, (gchar *[]) { certtool, "--generate-self-signed", "--template", template1_file, "--outfile", cacert, "--load-privkey", cakey, NULL }, FALSE); if (swtpm_rootca_password != NULL) certtool_env = g_environ_setenv(certtool_env, "GNUTLS_PIN", swtpm_rootca_password, TRUE); if (run_certtool(cmd, certtool_env, "Could not create root-CA:", NULL)) goto error; g_free(cmd); /* create the intermediate CA's key */ cmd = concat_arrays(NULL, (gchar *[]) { certtool, "--generate-privkey", "--outfile", (gchar *)signkey, NULL }, FALSE); if (signkey_password != NULL) cmd = concat_arrays(cmd, (gchar *[]){ "--password", (gchar *)signkey_password, NULL}, TRUE); if (run_certtool(cmd, certtool_env, "Could not create local-CA key", cakey)) goto error; if (chmod(signkey, S_IRUSR | S_IWUSR | S_IRGRP) != 0) { logerr(gl_LOGFILE, "Could not chmod %s: %s\n", signkey, strerror(errno)); goto error; } filecontent = "cn=swtpm-localca\n" "ca\n" "cert_signing_key\n" "expiration_days = 3600\n"; if (swtpm_rootca_password != NULL && signkey_password != NULL) fc = g_strdup_printf("%spassword = %s\n", filecontent, swtpm_rootca_password); else fc = g_strdup(filecontent); template2_file_fd = write_to_tempfile(&template2_file, (const unsigned char *)fc, strlen(fc)); if (template2_file_fd < 0) goto error; g_free(cmd); cmd = concat_arrays(NULL, (gchar *[]) { certtool, "--generate-certificate", "--template", template2_file, "--outfile", (gchar *)issuercert, "--load-privkey", (gchar *)signkey, "--load-ca-privkey", cakey, "--load-ca-certificate", cacert, NULL }, FALSE); if (signkey_password != NULL) certtool_env = g_environ_setenv(certtool_env, "GNUTLS_PIN", signkey_password, TRUE); else if (swtpm_rootca_password != NULL) certtool_env = g_environ_setenv(certtool_env, "GNUTLS_PIN", swtpm_rootca_password, TRUE); if (run_certtool(cmd, certtool_env, "Could not create local-CA:", NULL)) goto error; } ret = 0; error: if (template1_file_fd >= 0) close(template1_file_fd); if (template1_file != NULL) unlink(template1_file); if (template2_file_fd >= 0) close(template2_file_fd); if (template2_file != NULL) unlink(template2_file); g_strfreev(certtool_env); unlock_file(lockfd); return ret; } /* Extract the ECC parameters from a string like x=12,y=34,id=secp384r1. * This function returns 1 on error, 2 if the ECC parameters could be extracted * and 0 if no parameters could be extracted (likely a modulus). */ static gboolean extract_ecc_params(const gchar *ekparams, gchar **ecc_x, gchar **ecc_y, gchar **ecc_curveid) { regmatch_t pmatch[5]; regex_t preg; int ret; if (regcomp(&preg, "x=([0-9A-Fa-f]+),y=([0-9A-Fa-f]+)(,id=([^,]+))?", REG_EXTENDED) != 0) { logerr(gl_LOGFILE, "Internal error: Could not compile regex\n"); return 1; } ret = 0; if (regexec(&preg, ekparams, 5, pmatch, 0) == 0) { *ecc_x = g_strndup(&ekparams[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); *ecc_y = g_strndup(&ekparams[pmatch[2].rm_so], pmatch[2].rm_eo - pmatch[2].rm_so); if (pmatch[4].rm_so > 0 && pmatch[4].rm_eo > 0) *ecc_curveid = g_strndup(&ekparams[pmatch[4].rm_so], pmatch[4].rm_eo - pmatch[4].rm_so); ret = 2; } regfree(&preg); return ret; } /* Get the next serial number from the certserial file; if it contains * a non-numeric content start over with serial number '1'. */ static int get_next_serial(const gchar *certserial, const gchar *lockfile, gchar **serial_str) { g_autofree gchar *buffer = NULL; size_t buffer_len; unsigned long long serial, serial_n; char *endptr = NULL; int lockfd; int ret = 1; lockfd = lock_file(lockfile); if (lockfd < 0) return 1; if (access(certserial, R_OK) != 0) write_file(certserial, (unsigned char *)"1", 1); if (read_file(certserial, &buffer, &buffer_len) != 0) goto error; if (buffer_len > 0) { serial = strtoull(buffer, &endptr, 10); if (*endptr == '\0') { serial_n = serial + 1; } else { serial_n = 1; } } else { serial_n = 1; } *serial_str = g_strdup_printf("%llu", serial_n); write_file(certserial, (unsigned char *)*serial_str, strlen(*serial_str)); ret = 0; error: unlock_file(lockfd); return ret; } /* Create a TPM 1.2 or TPM 2 EK or platform cert */ static int create_cert(unsigned long flags, const gchar *typ, const gchar *directory, gchar *ekparams, const gchar *vmid, gchar **tpm_spec_params, gchar **tpm_attr_params, const gchar *signkey, const gchar *signkey_password, const gchar *issuercert, const gchar *parentkey_password, gchar **swtpm_cert_env, const gchar *certserial, const gchar *lockfile, const gchar *optsfile) { gchar ** optsfile_lines = NULL; g_autofree gchar **options = NULL; g_autofree gchar **keyparams = NULL; g_autofree gchar **cmd = NULL; g_autofree gchar *subject = NULL; g_autofree gchar *ecc_x = NULL; g_autofree gchar *ecc_y = NULL; g_autofree gchar *ecc_curveid = NULL; g_autofree gchar *certfile = NULL; g_autofree gchar *serial_str = NULL; gchar **to_free = NULL; gchar **split; const char *certtype; int signkey_pwd_fd = -1; int parentkey_pwd_fd = -1; g_autofree gchar *signkey_pwd_file = NULL; g_autofree gchar *signkey_pwd_file_param = NULL; g_autofree gchar *parentkey_pwd_file = NULL; g_autofree gchar *parentkey_pwd_file_param = NULL; gboolean success; g_autofree gchar *standard_output = NULL; g_autofree gchar *standard_error = NULL; g_autofree gchar *swtpm_cert_path = NULL; GError *error = NULL; gint exit_status; int ret = 1; size_t i, j; swtpm_cert_path = g_find_program_in_path("swtpm_cert"); if (swtpm_cert_path == NULL) { logerr(gl_LOGFILE, "Could not find swtpm_cert in PATH.\n"); return 1; } if (get_next_serial(certserial, lockfile, &serial_str) != 0) return 1; /* try to read the optsfile */ read_file_lines(optsfile, &optsfile_lines); /* split each line from the optsfile and add the stripped parameters to options */ for (i = 0; optsfile_lines != NULL && optsfile_lines[i] != NULL; i++) { gchar *chomped = g_strchomp(optsfile_lines[i]); if (strlen(chomped) == 0) continue; split = g_strsplit(chomped, " ", -1); for (j = 0; split[j] != NULL; j++) { chomped = g_strchomp(split[j]); if (strlen(chomped) > 0) { gchar *to_add = g_strdup(chomped); options = concat_arrays(options, (gchar *[]){to_add, NULL}, TRUE); /* need to collect this also to free later on */ to_free = concat_arrays(to_free, (gchar *[]){to_add, NULL}, TRUE); } } g_strfreev(split); } if (vmid != NULL) subject = g_strdup_printf("CN=%s", vmid); else subject = g_strdup("CN=unknown"); if (flags & SETUP_TPM2_F) options = concat_arrays(options, (gchar *[]){"--tpm2", NULL}, TRUE); else options = concat_arrays(options, (gchar *[]){"--add-header", NULL}, TRUE); if (strcmp(typ, "ek") == 0) { if (flags & ALLOW_SIGNING_F) options = concat_arrays(options, (gchar *[]){"--allow-signing", NULL}, TRUE); if (flags & DECRYPTION_F) options = concat_arrays(options, (gchar *[]){"--decryption", NULL}, TRUE); } switch (extract_ecc_params(ekparams, &ecc_x, &ecc_y, &ecc_curveid)) { case 1: goto error; case 2: keyparams = concat_arrays((gchar *[]){ "--ecc-x", ecc_x, "--ecc-y", ecc_y, NULL }, NULL, FALSE); if (ecc_curveid != NULL) keyparams = concat_arrays(keyparams, (gchar *[]){ "--ecc-curveid", ecc_curveid, NULL }, TRUE); break; case 0: keyparams = concat_arrays((gchar *[]){ "--modulus", ekparams, NULL}, NULL, FALSE); break; } cmd = concat_arrays((gchar *[]){ swtpm_cert_path, "--subject", subject, NULL }, options, FALSE); if (signkey_password != NULL) { signkey_pwd_fd = write_to_tempfile(&signkey_pwd_file, (unsigned char *)signkey_password, strlen(signkey_password)); if (signkey_pwd_fd < 0) goto error; signkey_pwd_file_param = g_strdup_printf("file:%s", signkey_pwd_file); cmd = concat_arrays(cmd, (gchar*[]){"--signkey-pwd", signkey_pwd_file_param, NULL}, TRUE); } if (parentkey_password != NULL) { parentkey_pwd_fd = write_to_tempfile(&parentkey_pwd_file, (unsigned char *)parentkey_password, strlen(parentkey_password)); if (parentkey_pwd_fd < 0) goto error; parentkey_pwd_file_param = g_strdup_printf("file:%s", parentkey_pwd_file); cmd = concat_arrays(cmd, (gchar*[]){"--parentkey-pwd", parentkey_pwd_file_param, NULL}, TRUE); } if (strcmp(typ, "ek") == 0) cmd = concat_arrays(cmd, tpm_spec_params, TRUE); cmd = concat_arrays(cmd, tpm_attr_params, TRUE); if (strcmp(typ, "platform") == 0) { certfile = g_strjoin(G_DIR_SEPARATOR_S, directory, "platform.cert", NULL); cmd = concat_arrays(cmd, (gchar *[]){ "--type", "platform", "--out-cert", certfile, NULL}, TRUE); } else { certfile = g_strjoin(G_DIR_SEPARATOR_S, directory, "ek.cert", NULL); cmd = concat_arrays(cmd, (gchar *[]){ "--out-cert", certfile, NULL }, TRUE); } cmd = concat_arrays(cmd, keyparams, TRUE); cmd = concat_arrays(cmd, (gchar *[]){ "--signkey", (gchar *)signkey, "--issuercert", (gchar *)issuercert, "--days", "3600", "--serial", (gchar *)serial_str, NULL }, TRUE); if (strcmp(typ, "ek") == 0) certtype = "EK"; else certtype = "platform"; #if 0 { g_autofree gchar *join = g_strjoinv(" ", cmd); fprintf(stderr, "Starting: %s\n", join); } #endif success = g_spawn_sync(NULL, cmd, swtpm_cert_env, G_SPAWN_DEFAULT, NULL, NULL, &standard_output, &standard_error, &exit_status, &error); if (!success) { logerr(gl_LOGFILE, "Could not run swtpm_cert: %s\n", error); g_error_free(error); goto error; } if (exit_status != 0) { logerr(gl_LOGFILE, "Could not create %s certificate locally\n", certtype); logerr(gl_LOGFILE, "%s\n", standard_error); goto error; } logit(gl_LOGFILE, "Successfully created %s certificate locally.\n", certtype); ret = 0; error: g_strfreev(optsfile_lines); g_strfreev(to_free); if (signkey_pwd_fd >= 0) close(signkey_pwd_fd); if (signkey_pwd_file) unlink(signkey_pwd_file); if (parentkey_pwd_fd >= 0) close(parentkey_pwd_fd); if (parentkey_pwd_file) unlink(parentkey_pwd_file); return ret; } static void usage(const char *prgname) { printf( "Usage: %s [options]\n" "\n" "The following options are supported:\n" "\n" "--type type The type of certificate to create: 'ek' or 'platform'\n" "--ek key-param The modulus of an RSA key or x=...,y=,... for an EC key\n" "--dir directory The directory to write the resulting certificate into\n" "--vmid vmid The ID of the virtual machine\n" "--optsfile file A file containing options to pass to swtpm_cert\n" "--configfile file A file containing configuration parameters for directory,\n" " signing key and password and certificate to use\n" "--logfile file A file to write a log into\n" "--tpm-spec-family s The implemented spec family, e.g., '2.0'\n" "--tpm-spec-revision i The spec revision of the TPM as integer; e.g., 146\n" "--tpm-spec-level i The spec level of the TPM; must be an integer; e.g. 0\n" "--tpm-manufacturer s The manufacturer of the TPM; e.g., id:00001014\n" "--tpm-model s The model of the TPM; e.g., 'swtpm'\n" "--tpm-version i The (firmware) version of the TPM; e.g., id:20160511\n" "--tpm2 Generate a certificate for a TPM 2\n" "--allow-signing The TPM 2's EK can be used for signing\n" "--decryption The TPM 2's EK can be used for decryption\n" "--help, -h, -? Display this help screen and exit\n" "\n" "\n" "The following environment variables are supported:\n" "\n" "SWTPM_ROOTCA_PASSWORD The root CA's private key password\n" "\n", prgname); } int main(int argc, char *argv[]) { int opt, option_index = 0; const static struct option long_options[] = { {"type", required_argument, NULL, 't'}, {"ek", required_argument, NULL, 'e'}, {"dir", required_argument, NULL, 'd'}, {"vmid", required_argument, NULL, 'v'}, {"optsfile", required_argument, NULL, 'o'}, {"configfile", required_argument, NULL, 'c'}, {"logfile", required_argument, NULL, 'l'}, {"tpm-spec-family", required_argument, NULL, 'f'}, {"tpm-spec-revision", required_argument, NULL, 'r'}, {"tpm-spec-level", required_argument, NULL, '1'}, {"tpm-manufacturer", required_argument, NULL, 'a'}, {"tpm-model", required_argument, NULL, 'm'}, {"tpm-version", required_argument, NULL, 's'}, {"tpm2", no_argument, NULL, '2'}, {"allow-signing", no_argument, NULL, 'i'}, {"decryption", no_argument, NULL, 'y'}, {"help", no_argument, NULL, 'h'}, }; g_autofree gchar *default_options_file = NULL; g_autofree gchar *default_config_file = NULL; g_autofree gchar *optsfile = NULL; g_autofree gchar *configfile = NULL; unsigned long flags = 0; g_autofree gchar *typ =g_strdup(""); g_autofree gchar *ekparams = g_strdup(""); g_autofree gchar *directory = g_strdup("."); /* default to current directory */ g_autofree gchar *vmid = NULL; g_autofree gchar *lockfile = NULL; g_autofree gchar *statedir = NULL; g_autofree gchar *signkey = NULL; g_autofree gchar *signkey_password = NULL; g_autofree gchar *parentkey_password = NULL; g_autofree gchar *issuercert = NULL; g_autofree gchar *certserial = NULL; gchar **tpm_spec_params = NULL; gchar **tpm_attr_params = NULL; gchar **config_file_lines = NULL; gchar **swtpm_cert_env = NULL; const struct passwd *curr_user; struct stat statbuf; int ret = 1; if (init(&default_options_file, &default_config_file) < 0) goto error; optsfile = g_strdup(default_options_file); configfile = g_strdup(default_config_file); while ((opt = getopt_long(argc, argv, "h?", long_options, &option_index)) != -1) { switch (opt) { case 't': /* --type */ g_free(typ); typ = g_strdup(optarg); break; case 'e': /* --ek */ g_free(ekparams); ekparams = g_strdup(optarg); break; case 'd': /* --dir */ g_free(directory); directory = g_strdup(optarg); break; case 'v': /* --vmid */ g_free(vmid); vmid = g_strdup(optarg); break; case 'o': /* --optsfile */ g_free(optsfile); optsfile = g_strdup(optarg); break; case 'c': /* --configfile */ g_free(configfile); configfile = g_strdup(optarg); break; case 'l': /* --logfile */ g_free(gl_LOGFILE); gl_LOGFILE = g_strdup(optarg); break; case 'f': /* --tpm-spec-family */ case 'r': /* --tpm-spec-revision */ case '1': /* --tpm-spec-level */ tpm_spec_params = concat_arrays(tpm_spec_params, (gchar *[]) { g_strdup_printf("--%s", long_options[option_index].name), g_strdup(optarg), NULL }, TRUE); break; case 'a': /* --tpm-manufacturer */ case 'm': /* --tpm-model */ case 's': /* --tpm-version */ tpm_attr_params = concat_arrays(tpm_attr_params, (gchar *[]) { g_strdup_printf("--%s", long_options[option_index].name), g_strdup(optarg), NULL }, TRUE); break; case '2': /* --tpm2 */ flags |= SETUP_TPM2_F; break; case 'i': /* --allow-signing */ flags |= ALLOW_SIGNING_F; break; case 'y': /* --decryption */ flags |= DECRYPTION_F; break; case '?': case 'h': /* --help */ usage(argv[0]); ret = 0; goto out; default: fprintf(stderr, "Unknown option code %d\n", opt); usage(argv[0]); goto error; } } curr_user = getpwuid(getuid()); if (gl_LOGFILE != NULL) { FILE *tmpfile; if (stat(gl_LOGFILE, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK) { fprintf(stderr, "Logfile must not be a symlink.\n"); goto error; } tmpfile = fopen(gl_LOGFILE, "a"); // do not truncate if (tmpfile == NULL) { fprintf(stderr, "Cannot write to logfile %s.\n", gl_LOGFILE); goto error; } fclose(tmpfile); } if (access(optsfile, R_OK) != 0) { logerr(gl_LOGFILE, "Need read rights on options file %s for user %s.\n", optsfile, curr_user ? curr_user->pw_name : ""); goto error; } if (access(configfile, R_OK) != 0) { logerr(gl_LOGFILE, "Need read rights on config file %s for user %s.\n", configfile, curr_user ? curr_user->pw_name : ""); goto error; } if (read_file_lines(configfile, &config_file_lines) != 0) goto error; statedir = get_config_value(config_file_lines, "statedir", NULL); if (statedir == NULL) { logerr(gl_LOGFILE, "Missing 'statedir' config value in config file %s.\n", configfile); goto error; } if (makedir(statedir, "statedir") != 0) goto error; if (access(statedir, W_OK | R_OK) != 0) { logerr(gl_LOGFILE, "Need read/write rights on statedir %s for user %s.\n", statedir, curr_user ? curr_user->pw_name : ""); goto error; } lockfile = g_strjoin(G_DIR_SEPARATOR_S, statedir, ".lock.swtpm-localca", NULL); if (stat(lockfile, &statbuf) == 0 && access(lockfile, W_OK | R_OK) != 0) { logerr(gl_LOGFILE, "Need read/write rights on %s for user %s.\n", lockfile, curr_user ? curr_user->pw_name : ""); goto error; } signkey = get_config_value(config_file_lines, "signingkey", NULL); if (signkey == NULL) { logerr(gl_LOGFILE, "Missing 'signingkey' config value in config file %s.\n", configfile); goto error; } if (!g_str_has_prefix(signkey, "tpmkey:file=") && !g_str_has_prefix(signkey, "tpmkey:uuid=") && !g_str_has_prefix(signkey, "pkcs11:")) { g_autofree gchar *d = g_path_get_dirname(signkey); if (makedir(d, "signkey") != 0) goto error; } signkey_password = get_config_value(config_file_lines, "signingkey_password", NULL); parentkey_password = get_config_value(config_file_lines, "parentkey_password", NULL); issuercert = get_config_value(config_file_lines, "issuercert", NULL); if (issuercert == NULL) { logerr(gl_LOGFILE, "Missing 'issuercert' config value in config file %s.\n", configfile); goto error; } { g_autofree gchar *d = g_path_get_dirname(issuercert); if (makedir(d, "issuercert") != 0) goto error; } swtpm_cert_env = g_get_environ(); // TPM keys are GNUTLS URIs... if (g_str_has_prefix(signkey, "tpmkey:file=") || g_str_has_prefix(signkey, "tpmkey:uuid=")) { gchar *tss_tcsd_hostname = get_config_value(config_file_lines, "TSS_TCSD_HOSTNAME", "localhost"); gchar *tss_tcsd_port = get_config_value(config_file_lines, "TSS_TCSD_PORT", "30003"); swtpm_cert_env = g_environ_setenv(swtpm_cert_env, "TSS_TCSD_HOSTNAME", tss_tcsd_hostname, TRUE); swtpm_cert_env = g_environ_setenv(swtpm_cert_env, "TSS_TCSD_PORT", tss_tcsd_port, TRUE); logit(gl_LOGFILE, "CA uses a GnuTLS TPM key; using TSS_TCSD_HOSTNAME=%s " \ "TSS_TCSD_PORT=%s\n", tss_tcsd_hostname, tss_tcsd_port); } else if (g_str_has_prefix(signkey, "pkcs11:")) { gchar *tmp = str_replace(signkey, "\\;", ";"); /* historical reasons ... */ g_free(signkey); signkey = tmp; if (signkey_password != NULL) { swtpm_cert_env = g_environ_setenv(swtpm_cert_env, "SWTPM_PKCS11_PIN", g_strdup(signkey_password), TRUE); logit(gl_LOGFILE, "CA uses a PKCS#11 key; using SWTPM_PKCS11_PIN\n"); } else { g_autofree gchar *swtpm_pkcs11_pin = NULL; swtpm_pkcs11_pin = get_config_value(config_file_lines, "SWTPM_PKCS11_PIN", "swtpm-tpmca"); swtpm_cert_env = g_environ_setenv(swtpm_cert_env, "SWTPM_PKCS11_PIN", swtpm_pkcs11_pin, TRUE); logit(gl_LOGFILE, "CA uses a PKCS#11 key; using SWTPM_PKCS11_PIN\n"); } ret = get_config_envvars(config_file_lines, &swtpm_cert_env); if (ret != 0) goto error; } else { int create_certs = 0; /* create certificate if either the signing key or issuer cert are missing */ if (access(signkey, R_OK) != 0) { if (stat(signkey, &statbuf) == 0) { logerr(gl_LOGFILE, "Need read rights on signing key %s for user %s.\n", signkey, curr_user ? curr_user->pw_name : ""); goto error; } create_certs = 1; } if (access(issuercert, R_OK) != 0) { if (stat(issuercert, &statbuf) == 0) { logerr(gl_LOGFILE, "Need read rights on issuer certificate %s for user %s.\n", issuercert, curr_user ? curr_user->pw_name : ""); goto error; } create_certs = 1; } if (create_certs) { logit(gl_LOGFILE, "Creating root CA and a local CA's signing key and issuer cert.\n"); if (create_localca_cert(lockfile, statedir, signkey, signkey_password, issuercert) != 0) { logerr(gl_LOGFILE, "Error creating local CA's signing key and cert.\n"); goto error; } if (access(signkey, R_OK) != 0) { logerr(gl_LOGFILE, "Need read rights on signing key %s for user %s.\n", signkey, curr_user ? curr_user->pw_name : ""); goto error; } } } if (access(issuercert, R_OK) != 0) { logerr(gl_LOGFILE, "Need read rights on issuer certificate %s for user %s.\n", issuercert, curr_user ? curr_user->pw_name : ""); goto error; } { g_autofree gchar *d = NULL; g_autofree gchar *p = g_strjoin(G_DIR_SEPARATOR_S, statedir, "certserial", NULL); certserial = get_config_value(config_file_lines, "certserial", p); d = g_path_get_dirname(certserial); if (makedir(d, "certserial") != 0) goto error; } ret = create_cert(flags, typ, directory, ekparams, vmid, tpm_spec_params, tpm_attr_params, signkey, signkey_password, issuercert, parentkey_password, swtpm_cert_env, certserial, lockfile, optsfile); out: error: g_strfreev(tpm_attr_params); g_strfreev(tpm_spec_params); exit(ret); } swtpm-0.6.3/samples/swtpm_localca.h000066400000000000000000000004551421141172300173370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_localca.h: Header file * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_LOCALCA_H #define SWTPM_LOCALCA_H #include extern gchar *gl_LOGFILE; #endif /* SWTPM_LOCALCA_H */ swtpm-0.6.3/samples/swtpm_localca_conf.h.in000066400000000000000000000004771421141172300207550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup_conf.h: Compile-time constants * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_LOCALCA_CONF_H #define SWTPM_LOCALCA_CONF_H #define SYSCONFDIR "@SYSCONFDIR@" #endif /* SWTPM_LOCALCA_CONF_H */ swtpm-0.6.3/samples/swtpm_localca_utils.c000066400000000000000000000077601421141172300205600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_localca_utils.c: Utility functions * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "swtpm_utils.h" #include "swtpm_localca.h" #include "swtpm_localca_utils.h" /* Create a directory pat (and all its predecessors) if it doesn't exist */ int makedir(const char *dirname, const char *purpose) { struct stat statbuf; if (stat(dirname, &statbuf) != 0) { logit(gl_LOGFILE, "Creating swtpm-localca dir '%s'.\n", dirname); if (g_mkdir_with_parents(dirname, S_IRWXU | S_IRWXG | S_IXGRP | S_IRGRP) == -1) { logerr(gl_LOGFILE, "Could not create directory for '%s': %s\n", purpose, strerror(errno)); return 1; } } return 0; } /* Get a configuration value given its name */ gchar *get_config_value(gchar **config_file_lines, const gchar *configname, const gchar *fallback) { g_autofree gchar *regex = g_strdup_printf("^%s[[:space:]]*=[[:space:]]*([^#\n]*).*", configname); gchar *result = NULL; regex_t preg; size_t idx; regmatch_t pmatch[2]; if (regcomp(&preg, regex, REG_EXTENDED) != 0) { logerr(gl_LOGFILE, "Internal error: Could not compile regex\n"); goto error; } for (idx = 0; config_file_lines[idx] != NULL; idx++) { const gchar *line = config_file_lines[idx]; if (regexec(&preg, line, 2, pmatch, 0) == 0) { g_autofree gchar *tmp = NULL; tmp = g_strndup(&line[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); g_strchomp(tmp); result = resolve_string(tmp); break; } } regfree(&preg); error: if (result == NULL) result = g_strdup(fallback); //printf("Found match for %s: |%s|\n", configname, result); return result; } /* Extract all environment variables from the config file and add them to * the given environent. * Environment variable lines must start with 'env:' and must not contain * trailing spaces or a comment starting with '#' */ int get_config_envvars(gchar **config_file_lines, gchar ***env) { const char *regex = "^env:([a-zA-Z_][a-zA-Z_0-9]*)[[:space:]]*=[[:space:]]*([^\n]*)"; regex_t preg; size_t idx; regmatch_t pmatch[3]; if (regcomp(&preg, regex, REG_EXTENDED) != 0) { logerr(gl_LOGFILE, "Internal error: Could not compile regex\n"); return 1; } for (idx = 0; config_file_lines[idx] != NULL; idx++) { const gchar *line = config_file_lines[idx]; if (regexec(&preg, line, 3, pmatch, 0) == 0) { g_autofree gchar *key = NULL, *value = NULL; key = g_strndup(&line[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); value = g_strndup(&line[pmatch[2].rm_so], pmatch[2].rm_eo - pmatch[2].rm_so); *env = g_environ_setenv(*env, key, value, TRUE); } } regfree(&preg); return 0; } /* flock a file; the file descriptor for the file to unlock later on is returned */ int lock_file(const gchar *lockfile) { int lockfd; mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; lockfd = open(lockfile, O_RDWR | O_CREAT, mode); if (lockfd < 0) { logerr(gl_LOGFILE, "Could not open lockfile %s: %s\n", lockfile, strerror(errno)); return -1; } if (flock(lockfd, LOCK_EX) < 0) { logerr(gl_LOGFILE, "Could not lock file %s: %s\n", lockfile, strerror(errno)); close(lockfd); return -1; } return lockfd; } /* unlock a file previously locked using lock_file */ void unlock_file(int lockfd) { if (lockfd >= 0) { flock(lockfd, LOCK_UN); close(lockfd); } } swtpm-0.6.3/samples/swtpm_localca_utils.h000066400000000000000000000011451421141172300205540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_localca_utils.h: Header file for swtpm_localca_utils.c * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_LOCALCA_UTILS_H #define SWTPM_LOCALCA_UTILS_H #include gchar *get_config_value(gchar **config_file_lines, const gchar *varname, const gchar *fallback); int get_config_envvars(gchar **config_file_lines, gchar ***env); int makedir(const char *dirname, const char *purpose); int lock_file(const gchar *lockfile); void unlock_file(int lockfd); #endif /* SWTPM_LOCALCA_UTILS_H */ swtpm-0.6.3/src/000077500000000000000000000000001421141172300134555ustar00rootroot00000000000000swtpm-0.6.3/src/Makefile.am000066400000000000000000000003331421141172300155100ustar00rootroot00000000000000# # src/Makefile.am # # For the license, see the COPYING file in the root directory. # SUBDIRS = \ utils \ swtpm \ swtpm_bios \ swtpm_cert \ swtpm_ioctl \ swtpm_setup if WITH_SELINUX SUBDIRS += \ selinux endif swtpm-0.6.3/src/selinux/000077500000000000000000000000001421141172300151445ustar00rootroot00000000000000swtpm-0.6.3/src/selinux/Makefile.am000066400000000000000000000034011421141172300171760ustar00rootroot00000000000000# # src/Makefile.am # # For the license, see the COPYING file in the root directory. # policiesconfdir = $(datadir)/selinux/packages POLICIES = \ swtpm.pp \ swtpm_svirt.pp if WITH_CUSE POLICIES += \ swtpmcuse.pp endif POLICIES_BZ2 = \ $(addsuffix .bz2,$(POLICIES)) policiesconf_DATA = \ $(POLICIES) swtpm.pp_FILES = \ $(addprefix $(top_srcdir)/src/selinux/,\ swtpm.fc swtpm.if swtpm.te) swtpm_svirt.pp_FILES = \ $(addprefix $(top_srcdir)/src/selinux/,\ swtpm_svirt.te swtpm.fc swtpm.if swtpm.te) if WITH_CUSE swtpmcuse.pp_FILES = \ $(addprefix $(top_srcdir)/src/selinux/,\ swtpmcuse.te swtpmcuse.fc swtpmcuse.if) endif all: $(POLICIES_BZ2) clean: $(RM) -r tmp $(POLICIES) $(POLICIES_BZ2) PRIORITY ?= 400 selinux-install: $(POLICIES_BZ2) @if test $(shell id -u) != 0; then \ echo "You have to be root for this operation"; exit 1; \ fi semodule --priority $(PRIORITY) --install $(POLICIES_BZ2) restorecon -i "$(prefix)/bin/swtpm" if WITH_CUSE restorecon -i "$(prefix)/bin/swtpm_cuse" endif selinux-uninstall: @if test $(shell id -u) != 0; then \ echo "You have to be root for this operation"; exit 1; \ fi semodule --priority $(PRIORITY) --remove $(patsubst %.pp.bz2,%,$(POLICIES_BZ2)) .PHONY: selinux-install selinux-uninstall %.pp.bz2: %.pp @echo Compressing $^ -\> $@ bzip2 -k -f -9 $^ .SECONDEXPANSION: .NOTPARALLEL: %.pp : $$($$@_FILES) echo "Creating $@ from $^" $(RM) -r $(top_srcdir)/src/selinux/tmp/ cp $^ ./ 2>/dev/null || true make -f /usr/share/selinux/devel/Makefile $@ $(RM) -r ./tmp/ if test $(shell pwd) != $(abspath $(top_srcdir)/src/selinux); then \ $(RM) *.te *.fc *.if; \ fi EXTRA_DIST = \ swtpm.fc \ swtpm.if \ swtpm.te \ swtpm_svirt.te \ swtpmcuse.fc \ swtpmcuse.if \ swtpmcuse.te CLEANFILES = *.pp *.pp.bz2 swtpm-0.6.3/src/selinux/swtpm.fc000066400000000000000000000001031421141172300166220ustar00rootroot00000000000000/usr/bin/swtpm -- gen_context(system_u:object_r:swtpm_exec_t,s0) swtpm-0.6.3/src/selinux/swtpm.if000066400000000000000000000026031421141172300166370ustar00rootroot00000000000000 ## policy for swtpm ######################################## ## ## Execute TEMPLATE in the swtpm domin. ## ## ## ## Domain allowed to transition. ## ## # interface(`swtpm_domtrans',` gen_require(` type swtpm_t, swtpm_exec_t; ') corecmd_search_bin($1) domtrans_pattern($1, swtpm_exec_t, swtpm_t) ') ######################################## ## ## Execute swtpm in the swtpm domain, and ## allow the specified role the swtpm domain. ## ## ## ## Domain allowed to transition ## ## ## ## ## The role to be allowed the swtpm domain. ## ## # interface(`swtpm_run',` gen_require(` type swtpm_t; attribute_role swtpm_roles; ') swtpm_domtrans($1) roleattribute $2 swtpm_roles; ') ######################################## ## ## Role access for swtpm ## ## ## ## Role allowed access ## ## ## ## ## User domain for the role ## ## # interface(`swtpm_role',` gen_require(` type swtpm_t; attribute_role swtpm_roles; ') roleattribute $1 swtpm_roles; swtpm_domtrans($2) ps_process_pattern($2, swtpm_t) allow $2 swtpm_t:process { signull signal sigkill }; ') swtpm-0.6.3/src/selinux/swtpm.te000066400000000000000000000012251421141172300166500ustar00rootroot00000000000000policy_module(swtpm, 1.0.0) ######################################## # # Declarations # attribute_role swtpm_roles; roleattribute system_r swtpm_roles; type swtpm_t; type swtpm_exec_t; application_domain(swtpm_t, swtpm_exec_t) role swtpm_roles types swtpm_t; ######################################## # # swtpm local policy # allow swtpm_t self:capability { setgid setuid dac_override dac_read_search }; allow swtpm_t self:fifo_file manage_fifo_file_perms; allow swtpm_t self:unix_stream_socket create_stream_socket_perms; domain_use_interactive_fds(swtpm_t) files_read_etc_files(swtpm_t) auth_use_nsswitch(swtpm_t) miscfiles_read_localization(swtpm_t) swtpm-0.6.3/src/selinux/swtpm_svirt.te000066400000000000000000000023271421141172300201030ustar00rootroot00000000000000policy_module(swtpm_svirt,1.0) require { type svirt_t; type svirt_tcg_t; type swtpm_exec_t; type virtd_t; type user_tmp_t; type virt_var_run_t; } swtpm_domtrans(svirt_t) swtpm_domtrans(svirt_tcg_t) #============= svirt_t ============== allow svirt_t virtd_t:fifo_file { read write }; allow svirt_t virtd_t:process sigchld; allow svirt_t user_tmp_t:sock_file { create setattr }; allow svirt_t swtpm_exec_t:file { entrypoint map }; # libvirt specific rules needed on F28 allow svirt_t virtd_t:unix_stream_socket { read write getopt getattr accept }; # virt_var_run_t rules needed on F30 allow svirt_t virt_var_run_t:dir { add_name remove_name write }; allow svirt_t virt_var_run_t:file { create getattr open read unlink write }; allow svirt_t virt_var_run_t:sock_file { create setattr }; allow svirt_tcg_t virtd_t:fifo_file { write read }; allow svirt_tcg_t virt_var_run_t:sock_file { create setattr }; allow svirt_tcg_t virt_var_run_t:file { create getattr open read unlink write }; allow svirt_tcg_t virt_var_run_t:dir { write add_name remove_name }; allow svirt_tcg_t swtpm_exec_t:file { entrypoint map }; # libvirt specific rules needed on F28 allow svirt_tcg_t virtd_t:unix_stream_socket { read write getopt getattr accept }; swtpm-0.6.3/src/selinux/swtpmcuse.fc000066400000000000000000000001131421141172300175030ustar00rootroot00000000000000/usr/bin/swtpm_cuse -- gen_context(system_u:object_r:swtpmcuse_exec_t,s0) swtpm-0.6.3/src/selinux/swtpmcuse.if000066400000000000000000000027431421141172300175240ustar00rootroot00000000000000 ## policy for swtpmcuse ######################################## ## ## Execute TEMPLATE in the swtpmcuse domin. ## ## ## ## Domain allowed to transition. ## ## # interface(`swtpmcuse_domtrans',` gen_require(` type swtpmcuse_t, swtpmcuse_exec_t; ') corecmd_search_bin($1) domtrans_pattern($1, swtpmcuse_exec_t, swtpmcuse_t) ') ######################################## ## ## Execute swtpmcuse in the swtpmcuse domain, and ## allow the specified role the swtpmcuse domain. ## ## ## ## Domain allowed to transition ## ## ## ## ## The role to be allowed the swtpmcuse domain. ## ## # interface(`swtpmcuse_run',` gen_require(` type swtpmcuse_t; attribute_role swtpmcuse_roles; ') swtpmcuse_domtrans($1) roleattribute $2 swtpmcuse_roles; ') ######################################## ## ## Role access for swtpmcuse ## ## ## ## Role allowed access ## ## ## ## ## User domain for the role ## ## # interface(`swtpmcuse_role',` gen_require(` type swtpmcuse_t; attribute_role swtpmcuse_roles; ') roleattribute $1 swtpmcuse_roles; swtpmcuse_domtrans($2) ps_process_pattern($2, swtpmcuse_t) allow $2 swtpmcuse_t:process { signull signal sigkill }; ') swtpm-0.6.3/src/selinux/swtpmcuse.te000066400000000000000000000013311421141172300175260ustar00rootroot00000000000000policy_module(swtpmcuse, 1.0.0) ######################################## # # Declarations # attribute_role swtpmcuse_roles; roleattribute system_r swtpmcuse_roles; type swtpmcuse_t; type swtpmcuse_exec_t; application_domain(swtpmcuse_t, swtpmcuse_exec_t) role swtpmcuse_roles types swtpmcuse_t; ######################################## # # swtpmcuse local policy # allow swtpmcuse_t self:capability { setgid setuid dac_override dac_read_search }; allow swtpmcuse_t self:fifo_file manage_fifo_file_perms; allow swtpmcuse_t self:unix_stream_socket create_stream_socket_perms; domain_use_interactive_fds(swtpmcuse_t) files_read_etc_files(swtpmcuse_t) auth_use_nsswitch(swtpmcuse_t) miscfiles_read_localization(swtpmcuse_t) swtpm-0.6.3/src/swtpm/000077500000000000000000000000001421141172300146275ustar00rootroot00000000000000swtpm-0.6.3/src/swtpm/Makefile.am000066400000000000000000000046261421141172300166730ustar00rootroot00000000000000# # src/swtpm/Makefile.am # # For the license, see the COPYING file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = \ capabilities.h \ common.h \ ctrlchannel.h \ key.h \ locality.h \ logging.h \ main.h \ mainloop.h \ options.h \ osx.h \ pidfile.h \ seccomp_profile.h \ server.h \ swtpm_aes.h \ swtpm_debug.h \ swtpm_io.h \ swtpm_nvfile.h \ threadpool.h \ tlv.h \ tpmlib.h \ tpmstate.h \ utils.h \ vtpm_proxy.h privlibdir = $(libdir)/@PACKAGE@ privlib_LTLIBRARIES = libswtpm_libtpms.la libswtpm_libtpms_la_SOURCES = \ capabilities.c \ common.c \ ctrlchannel.c \ key.c \ logging.c \ mainloop.c \ options.c \ pidfile.c \ seccomp_profile.c \ server.c \ swtpm_aes.c \ swtpm_debug.c \ swtpm_io.c \ swtpm_nvfile.c \ tlv.c \ tpmlib.c \ tpmstate.c \ utils.c if WITH_CUSE libswtpm_libtpms_la_SOURCES += \ threadpool.c endif libswtpm_libtpms_la_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/swtpm \ $(MY_CFLAGS) \ $(CFLAGS) \ $(HARDENING_CFLAGS) \ $(GLIB_CFLAGS) \ $(LIBSECCOMP_CFLAGS) \ $(LIBCRYPTO_EXTRA_CFLAGS) libswtpm_libtpms_la_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) libswtpm_libtpms_la_LIBADD = \ $(LIBTPMS_LIBS) \ $(GLIB_LIBS) \ $(LIBRT_LIBS) \ $(LIBSECCOMP_LIBS) \ $(LIBCRYPTO_LIBS) bin_PROGRAMS = swtpm if WITH_CUSE bin_PROGRAMS += swtpm_cuse endif swtpm_DEPENDENCIES = $(privlib_LTLIBRARIES) swtpm_SOURCES = \ main.c \ osx.c \ swtpm.c \ swtpm_chardev.c if WITH_CUSE swtpm_SOURCES += cuse_tpm.c endif swtpm_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/swtpm \ $(MY_CFLAGS) \ $(HARDENING_CFLAGS) \ $(GLIB_CFLAGS) \ $(LIBFUSE_CFLAGS) \ -DHAVE_SWTPM_CUSE_MAIN swtpm_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) swtpm_LDADD = \ libswtpm_libtpms.la \ $(LIBFUSE_LIBS) \ $(GLIB_LIBS) \ $(GTHREAD_LIBS) \ $(LIBTPMS_LIBS) swtpm_cuse_DEPENDENCIES = $(privlib_LTLIBRARIES) swtpm_cuse_SOURCES = \ cuse_tpm.c swtpm_cuse_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include/swtpm \ $(MY_CFLAGS) \ $(GLIB_CFLAGS) \ $(LIBFUSE_CFLAGS) \ $(HARDENING_CFLAGS) swtpm_cuse_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) swtpm_cuse_LDADD = \ libswtpm_libtpms.la \ $(LIBFUSE_LIBS) \ $(GLIB_LIBS) \ $(GTHREAD_LIBS) \ $(LIBTPMS_LIBS) AM_CPPFLAGS = LDADD = -ltpms CLEANFILES = *.gcno *.gcda *.gcov swtpm-0.6.3/src/swtpm/capabilities.c000066400000000000000000000112331421141172300174240ustar00rootroot00000000000000/* * capabilities.c -- capabilities * * (c) Copyright IBM Corporation 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #define _GNU_SOURCE #include #include #include #include #include "capabilities.h" #include "logging.h" /* Convert the RSA key size indicators supported by libtpms into capability * strings. * libtpms may return us something like this here: * "TPMAttributes":{"manufacturer":"id:00001014",\ * "version":"id:20191023","model":"swtpm","RSAKeySizes":[1024,2048,3072]}} * * or an older version may not report RSA keysizes: * "TPMAttributes":{"manufacturer":"id:00001014",\ * "version":"id:20191023","model":"swtpm"}} */ static int get_rsa_keysize_caps(char **keysizecaps) { int ret = 0; char *start, *endptr; const char *needle = "\"RSAKeySizes\":["; char *info_data = TPMLIB_GetInfo(4 /*TPMLIB_INFO_TPMFEATURES*/); char buffer[128]; off_t offset = 0; int n; if (!info_data) goto oom; start = strstr(info_data, needle); if (start) { start += strlen(needle); while (1) { unsigned long int keysize = strtoul(start, &endptr, 10); if (*endptr != ',' && *endptr != ']') { logprintf(STDERR_FILENO, "Malformed TPMLIB_GetInfo() string\n"); ret = -1; goto cleanup; } n = snprintf(buffer + offset, sizeof(buffer) - offset, ", \"rsa-keysize-%lu\"", keysize); if (n < 0 || (unsigned)n >= sizeof(buffer) - offset) { logprintf(STDERR_FILENO, "%s: buffer is too small\n", __func__); ret = -1; goto cleanup; } if (*endptr == ']') break; offset += n; start = endptr + 1; } *keysizecaps = strndup(buffer, sizeof(buffer) - 1); if (*keysizecaps == NULL) goto oom; } cleanup: free(info_data); return ret; oom: logprintf(STDERR_FILENO, "Out of memory\n"); ret = -1; goto cleanup; } int capabilities_print_json(bool cusetpm) { char *string = NULL; int ret = -1; int n; #ifdef WITH_SECCOMP const char *cmdarg_seccomp = "\"cmdarg-seccomp\", "; #else const char *cmdarg_seccomp = ""; #endif char *keysizecaps = NULL; ret = get_rsa_keysize_caps(&keysizecaps); if (ret < 0) goto cleanup; n = asprintf(&string, "{ " "\"type\": \"swtpm\", " "\"features\": [ " "%s%s%s%s%s%s" " ] " "}", !cusetpm ? "\"tpm-send-command-header\", ": "", !cusetpm ? "\"flags-opt-startup\", " : "", cmdarg_seccomp, true ? "\"cmdarg-key-fd\", " : "", true ? "\"cmdarg-pwd-fd\"" : "", keysizecaps ? keysizecaps : "" ); if (n < 0) { logprintf(STDERR_FILENO, "Out of memory\n"); goto cleanup; } ret = 0; fprintf(stdout, "%s\n", string); cleanup: free(keysizecaps); free(string); return ret; } swtpm-0.6.3/src/swtpm/capabilities.h000066400000000000000000000034271421141172300174370ustar00rootroot00000000000000/* * capabilities.h -- capabilities * * (c) Copyright IBM Corporation 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SWTPM_CAPABILITIES_H #define SWTPM_CAPABILITIES_H #include int capabilities_print_json(bool cusetpm); #endif /* SWTPM_CAPABILITIES_H */ swtpm-0.6.3/src/swtpm/common.c000066400000000000000000001010051421141172300162600ustar00rootroot00000000000000/* * common.c -- Common code for swtpm and swtpm_cuse * * (c) Copyright IBM Corporation 2014, 2015, 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_SECCOMP # include #endif #include #include "common.h" #include "options.h" #include "key.h" #include "locality.h" #include "logging.h" #include "swtpm_nvfile.h" #include "pidfile.h" #include "tpmstate.h" #include "ctrlchannel.h" #include "server.h" #include "seccomp_profile.h" #include "tpmlib.h" /* --log %s */ static const OptionDesc logging_opt_desc[] = { { .name = "file", .type = OPT_TYPE_STRING, }, { .name = "fd", .type = OPT_TYPE_INT, }, { .name = "level", .type = OPT_TYPE_UINT, }, { .name = "prefix", .type = OPT_TYPE_STRING, }, { .name = "truncate", .type = OPT_TYPE_BOOLEAN, }, END_OPTION_DESC }; /* --key %s */ static const OptionDesc key_opt_desc[] = { { .name = "file", .type = OPT_TYPE_STRING, }, { .name = "mode", .type = OPT_TYPE_STRING, }, { .name = "format", .type = OPT_TYPE_STRING, }, { .name = "remove", .type = OPT_TYPE_BOOLEAN, }, { .name = "pwdfile", .type = OPT_TYPE_STRING, }, { .name = "kdf", .type = OPT_TYPE_STRING, }, { .name = "fd", .type = OPT_TYPE_INT, }, { .name = "pwdfd", .type = OPT_TYPE_INT, }, END_OPTION_DESC }; /* --pid %s */ static const OptionDesc pid_opt_desc[] = { { .name = "file", .type = OPT_TYPE_STRING, }, { .name = "fd", .type = OPT_TYPE_INT, }, END_OPTION_DESC }; /* --state %s */ static const OptionDesc tpmstate_opt_desc[] = { { .name = "dir", .type = OPT_TYPE_STRING, }, { .name = "mode", .type = OPT_TYPE_MODE_T, }, END_OPTION_DESC }; static const OptionDesc ctrl_opt_desc[] = { { .name = "type", .type = OPT_TYPE_STRING, }, { .name = "path", .type = OPT_TYPE_STRING, }, { .name = "port", .type = OPT_TYPE_INT, }, { .name = "bindaddr", .type = OPT_TYPE_STRING, }, { .name = "ifname", .type = OPT_TYPE_STRING, }, { .name = "fd", .type = OPT_TYPE_INT, }, { .name = "clientfd", .type = OPT_TYPE_INT, }, { .name = "mode", .type = OPT_TYPE_MODE_T, }, { .name = "uid", .type = OPT_TYPE_UID_T, }, { .name = "gid", .type = OPT_TYPE_GID_T, }, END_OPTION_DESC }; static const OptionDesc server_opt_desc[] = { { .name = "type", .type = OPT_TYPE_STRING, }, { .name = "path", .type = OPT_TYPE_STRING, }, { .name = "port", .type = OPT_TYPE_INT, }, { .name = "bindaddr", .type = OPT_TYPE_STRING, }, { .name = "ifname", .type = OPT_TYPE_STRING, }, { .name = "fd", .type = OPT_TYPE_INT, }, { .name = "disconnect", .type = OPT_TYPE_BOOLEAN, }, { .name = "mode", .type = OPT_TYPE_MODE_T, }, { .name = "uid", .type = OPT_TYPE_UID_T, }, { .name = "gid", .type = OPT_TYPE_GID_T, }, END_OPTION_DESC }; static const OptionDesc locality_opt_desc[] = { { .name = "reject-locality-4", .type = OPT_TYPE_BOOLEAN, }, { .name = "allow-set-locality", .type = OPT_TYPE_BOOLEAN, }, END_OPTION_DESC }; static const OptionDesc flags_opt_desc[] = { { .name = "not-need-init", .type = OPT_TYPE_BOOLEAN, }, { .name = "startup-none", .type = OPT_TYPE_BOOLEAN, }, { .name = "startup-clear", .type = OPT_TYPE_BOOLEAN, }, { .name = "startup-state", .type = OPT_TYPE_BOOLEAN, }, { .name = "startup-deactivated", .type = OPT_TYPE_BOOLEAN, }, END_OPTION_DESC }; #ifdef WITH_SECCOMP static const OptionDesc seccomp_opt_desc[] = { { .name = "action", .type = OPT_TYPE_STRING, }, END_OPTION_DESC }; #endif /* * handle_log_options: * Parse and act upon the parsed log options. Initialize the logging. * @options: the log options * * Returns 0 on success, -1 on failure. */ int handle_log_options(char *options) { char *error = NULL; const char *logfile = NULL, *logprefix = NULL; int logfd; unsigned int loglevel; bool logtruncate; OptionValues *ovs = NULL; if (!options) return 0; ovs = options_parse(options, logging_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing logging options: %s\n", error); free(error); return -1; } logfile = option_get_string(ovs, "file", NULL); logfd = option_get_int(ovs, "fd", -1); loglevel = option_get_uint(ovs, "level", 0); logprefix = option_get_string(ovs, "prefix", NULL); logtruncate = option_get_bool(ovs, "truncate", false); if (logfile && (log_init(logfile, logtruncate) < 0)) { logprintf(STDERR_FILENO, "Could not open logfile for writing: %s\n", strerror(errno)); goto error; } else if (logfd >= 0 && (log_init_fd(logfd) < 0)) { logprintf(STDERR_FILENO, "Could not access logfile using fd %d: %s\n", logfd, strerror(errno)); goto error; } if ((logfile || logfd) && !loglevel) loglevel = 1; if (log_set_prefix(logprefix) < 0) { logprintf(STDERR_FILENO, "Could not set logging prefix. Out of memory?\n"); goto error; } if (log_set_level(loglevel) < 0) { logprintf(STDERR_FILENO, "Could not set log level. Out of memory?"); goto error; } option_values_free(ovs); return 0; error: option_values_free(ovs); return -1; } /* * parse_key_options: * Parse and act upon the parsed key options. * * @options: the key options to parse * @key: buffer to hold the key * @maxkeylen: size of the buffer (= max. size the key can have) * @keylen: the length of the parsed key * @encmode: the encryption mode as determined from the options * * Returns 0 on success, -1 on failure. */ static int parse_key_options(char *options, unsigned char *key, size_t maxkeylen, size_t *keylen, enum encryption_mode *encmode) { OptionValues *ovs = NULL; char *error = NULL; const char *keyfile = NULL; const char *pwdfile = NULL; const char *tmp; enum key_format keyformat; enum kdf_identifier kdfid; size_t mode_keylength; int ret; int keyfile_fd = -1; int pwdfile_fd = -1; ovs = options_parse(options, key_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing key options: %s\n", error); goto error; } keyfile = option_get_string(ovs, "file", NULL); keyfile_fd = option_get_int(ovs, "fd", -1); pwdfile = option_get_string(ovs, "pwdfile", NULL); pwdfile_fd = option_get_int(ovs, "pwdfd", -1); if (!keyfile && keyfile_fd == -1 && !pwdfile && pwdfile_fd == -1) { logprintf(STDERR_FILENO, "Either file=, fd=, pwdfile=, or pwdfd= is required for key option\n"); goto error; } tmp = option_get_string(ovs, "format", NULL); keyformat = key_format_from_string(tmp ? tmp : "hex"); if (keyformat == KEY_FORMAT_UNKNOWN) goto error; tmp = option_get_string(ovs, "mode", NULL); *encmode = encryption_mode_from_string(tmp ? tmp : "aes-128-cbc", &mode_keylength); if (*encmode == ENCRYPTION_MODE_UNKNOWN) { logprintf(STDERR_FILENO, "Unknown encryption mode '%s'.\n", tmp); goto error; } if (mode_keylength > maxkeylen) { /* program error ... */ logprintf(STDERR_FILENO, "Requested key size %zu larger than supported size %zu.\n", mode_keylength, maxkeylen); goto error; } if (keyfile != NULL) { if (key_load_key(keyfile, keyformat, key, keylen, mode_keylength) < 0) goto error; } else if (keyfile_fd >= 0) { if (key_load_key_fd(keyfile_fd, keyformat, key, keylen, mode_keylength) < 0) goto error; } else { tmp = option_get_string(ovs, "kdf", "pbkdf2"); kdfid = kdf_identifier_from_string(tmp); if (kdfid == KDF_IDENTIFIER_UNKNOWN) { logprintf(STDERR_FILENO, "Unknown kdf '%s'.\n", tmp); goto error; } /* no key file, so must be pwdfile or pwdfile_fd */ if (pwdfile) { if (key_from_pwdfile(pwdfile, key, keylen, mode_keylength, kdfid) < 0) goto error; } else { if (key_from_pwdfile_fd(pwdfile_fd, key, keylen, mode_keylength, kdfid) < 0) goto error; } } if (option_get_bool(ovs, "remove", false)) { if (keyfile) unlink(keyfile); if (pwdfile) unlink(pwdfile); } ret = 0; exit: option_values_free(ovs); if (keyfile_fd >= 0) close(keyfile_fd); if (pwdfile_fd >= 0) close(pwdfile_fd); return ret; error: ret = -1; free(error); goto exit; } /* * handle_key_options: * Parse and act upon the parsed key options. Set global values related * to the options found. * @options: the key options to parse * * Returns 0 on success, -1 on failure. */ int handle_key_options(char *options) { enum encryption_mode encmode = ENCRYPTION_MODE_UNKNOWN; unsigned char key[256/8]; size_t maxkeylen = sizeof(key); size_t keylen; int ret = 0; if (!options) return 0; if (parse_key_options(options, key, maxkeylen, &keylen, &encmode) < 0) { ret = -1; goto error; } if (SWTPM_NVRAM_Set_FileKey(key, keylen, encmode) != TPM_SUCCESS) { ret = -1; goto error; } error: /* Wipe to ensure we don't leave a key on the stack */ memset(key, 0, maxkeylen); return ret; } /* * handle_migration_key_options: * Parse and act upon the parsed key options. Set global values related * to the options found. * @options: the key options to parse * * Returns 0 on success, -1 on failure. */ int handle_migration_key_options(char *options) { enum encryption_mode encmode = ENCRYPTION_MODE_UNKNOWN; unsigned char key[256/8]; size_t maxkeylen = sizeof(key); size_t keylen; int ret = 0; if (!options) return 0; if (parse_key_options(options, key, maxkeylen, &keylen, &encmode) < 0) { ret = -1; goto error; } if (SWTPM_NVRAM_Set_MigrationKey(key, keylen, encmode) != TPM_SUCCESS) { ret = -1; goto error; } error: /* Wipe to ensure we don't leave a key on the stack */ memset(key, 0, maxkeylen); return ret; } /* * parse_pid_options: * Parse and act upon the parsed 'pid' options. * * @options: the 'pid' options to parse * @pidfile: Point to pointer for pidfile * @pidfilefd: Pointer to file descriptor for pidfile * * Returns 0 on success, -1 on failure. */ static int parse_pid_options(char *options, char **pidfile, int *pidfilefd) { OptionValues *ovs = NULL; char *error = NULL; const char *filename = NULL; struct stat stat; ovs = options_parse(options, pid_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing pid options: %s\n", error); goto error; } filename = option_get_string(ovs, "file", NULL); *pidfilefd = option_get_int(ovs, "fd", -1); if (!filename && *pidfilefd < 0) { logprintf(STDERR_FILENO, "The file or fd parameter is required for the pid option.\n"); goto error; } if (filename) { *pidfile = strdup(filename); if (!*pidfile) { logprintf(STDERR_FILENO, "Out of memory."); goto error; } } else { if (fstat(*pidfilefd, &stat) < 0 || !S_ISREG(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for pid file\n", *pidfilefd); goto error; } } option_values_free(ovs); return 0; error: option_values_free(ovs); if (*pidfilefd >= 0) close(*pidfilefd); free(error); return -1; } /* * handle_pidfile_options: * Parse and act upon the parse pidfile options. * * @options: the pidfile options to parse * * Returns 0 on success, -1 on failure. */ int handle_pid_options(char *options) { char *pidfile = NULL; int pidfilefd = -1; int ret = 0; if (!options) return 0; if (parse_pid_options(options, &pidfile, &pidfilefd) < 0) return -1; if (pidfile && pidfile_set(pidfile) < 0) ret = -1; else if (pidfile_set_fd(pidfilefd) < 0) ret = -1; free(pidfile); return ret; } /* * parse_tpmstate_options: * Parse and act upon the parsed 'tpmstate' options. * * @options: the 'pid' options to parse * @tpmstatedir: Point to pointer for tpmstatedir * @mode: the mode of the TPM's state files * * Returns 0 on success, -1 on failure. */ static int parse_tpmstate_options(char *options, char **tpmstatedir, mode_t *mode) { OptionValues *ovs = NULL; char *error = NULL; const char *directory = NULL; ovs = options_parse(options, tpmstate_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing tpmstate options: %s\n", error); goto error; } directory = option_get_string(ovs, "dir", NULL); if (!directory) { logprintf(STDERR_FILENO, "The file parameter is required for the tpmstate option.\n"); goto error; } *mode = option_get_mode_t(ovs, "mode", 0640); *tpmstatedir = strdup(directory); if (!*tpmstatedir) { logprintf(STDERR_FILENO, "Out of memory."); goto error; } option_values_free(ovs); return 0; error: free(error); option_values_free(ovs); return -1; } /* * handle_tpmstate_options: * Parse and act upon the parsed 'tpmstate' options. * * @options: the tpmstate options to parse * * Returns 0 on success, -1 on failure. */ int handle_tpmstate_options(char *options) { char *tpmstatedir = NULL; int ret = 0; mode_t mode; if (!options) return 0; if (parse_tpmstate_options(options, &tpmstatedir, &mode) < 0) return -1; if (tpmstate_set_dir(tpmstatedir) < 0 || tpmstate_set_mode(mode) < 0) ret = -1; free(tpmstatedir); return ret; } /* * unixio_open_socket: Open a UnixIO socket and return file descriptor * * @path: UnixIO socket path * @perm: UnixIO socket permissions * @uid: uid to set the ownership of the UnixIO socket path to * @gid: gid to set the ownership of the UnixIO socket path to */ static int unixio_open_socket(const char *path, mode_t perm, uid_t uid, gid_t gid) { struct sockaddr_un su; int fd = -1, n; size_t len; su.sun_family = AF_UNIX; len = sizeof(su.sun_path); n = snprintf(su.sun_path, len, "%s", path); if (n < 0) { logprintf(STDERR_FILENO, "Could not nsprintf path to UnixIO socket\n"); return -1; } if (n >= (int)len) { logprintf(STDERR_FILENO, "Path for UnioIO socket is too long\n"); return -1; } unlink(su.sun_path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { logprintf(STDERR_FILENO, "Could not open UnixIO socket\n"); return -1; } len = strlen(su.sun_path) + sizeof(su.sun_family) + 1; n = bind(fd, (struct sockaddr *)&su, len); if (n < 0) { logprintf(STDERR_FILENO, "Could not open UnixIO socket: %s\n", strerror(errno)); goto error; } if (chmod(su.sun_path, perm) < 0) { logprintf(STDERR_FILENO, "Could not change permssions on UnixIO socket: %s\n", strerror(errno)); goto error; } if ((uid != (uid_t)-1 || gid != (gid_t)-1) && chown(su.sun_path, uid, gid) < 0) { logprintf(STDERR_FILENO, "Could not change ownership of UnixIO socket to " "%u:%u %s\n", uid, gid, strerror(errno)); goto error; } n = listen(fd, 1); if (n < 0) { logprintf(STDERR_FILENO, "Cannot listen on UnixIO socket: %s\n", strerror(errno)); goto error; } return fd; error: close(fd); return -1; } /* * tcp_open_socket: Open a TCP port and return the file descriptor * * @port: port number * @bindadddr: the address to bind the socket to */ static int tcp_open_socket(unsigned short port, const char *bindaddr, const char *ifname) { int fd = -1, n, af, opt; struct sockaddr_in si; struct sockaddr_in6 si6; struct sockaddr *sa; socklen_t sa_len; void *dst; if (index(bindaddr, ':')) { af = AF_INET6; memset(&si6, 0, sizeof(si6)); si6.sin6_family = af; si6.sin6_port = htons(port); dst = &si6.sin6_addr.s6_addr; sa = (struct sockaddr *)&si6; sa_len = sizeof(si6); } else { af = AF_INET; si.sin_family = af; si.sin_port = htons(port); memset(&si.sin_zero, 0, sizeof(si.sin_zero)); dst = &si.sin_addr.s_addr; sa = (struct sockaddr *)&si; sa_len = sizeof(si); } n = inet_pton(af, bindaddr, dst); if (n <= 0) { logprintf(STDERR_FILENO, "Could not parse the bind address '%s'\n", bindaddr); return -1; } if (af == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL(&si6.sin6_addr)) { if (!ifname) { logprintf(STDERR_FILENO, "Missing interface name for link local address\n"); return -1; } n = if_nametoindex(ifname); if (!n) { logprintf(STDERR_FILENO, "Could not convert interface name '%s' to " "index: %s\n", ifname, strerror(errno)); return -1; } si6.sin6_scope_id = n; } } fd = socket(af, SOCK_STREAM, 0); if (fd < 0) { logprintf(STDERR_FILENO, "Could not open TCP socket\n"); return -1; } opt = 1; n = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (n < 0) { logprintf(STDERR_FILENO, "Could not set socket option SO_REUSEADDR: %s\n", strerror(errno)); goto error; } n = bind(fd, sa, sa_len); if (n < 0) { logprintf(STDERR_FILENO, "Could not open TCP socket: %s\n", strerror(errno)); goto error; } n = listen(fd, 1); if (n < 0) { logprintf(STDERR_FILENO, "Cannot listen on TCP socket: %s\n", strerror(errno)); goto error; } return fd; error: close(fd); return -1; } /* * parse_ctrlchannel_options: * Parse the 'ctrl' (control channel) options. * * @options: the control channel options to parse * * Returns 0 on success, -1 on failure. */ static int parse_ctrlchannel_options(char *options, struct ctrlchannel **cc) { OptionValues *ovs = NULL; char *error = NULL; const char *type, *path, *bindaddr, *ifname; int fd, clientfd, port; struct stat stat; mode_t mode; uid_t uid; gid_t gid; ovs = options_parse(options, ctrl_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing ctrl options: %s\n", error); goto error; } type = option_get_string(ovs, "type", NULL); if (!type) { logprintf(STDERR_FILENO, "Missing type parameter for control channel\n"); goto error; } if (!strcmp(type, "unixio")) { path = option_get_string(ovs, "path", NULL); fd = option_get_int(ovs, "fd", -1); clientfd = option_get_int(ovs, "clientfd", -1); mode = option_get_mode_t(ovs, "mode", 0770); uid = option_get_uid_t(ovs, "uid", -1); gid = option_get_gid_t(ovs, "gid", -1); if (fd >= 0) { if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for UnixIO control channel\n", fd); goto error; } *cc = ctrlchannel_new(fd, false, NULL); } else if (clientfd >= 0) { if (fstat(clientfd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for UnixIO client control" " channel\n", clientfd); goto error; } *cc = ctrlchannel_new(clientfd, true, NULL); } else if (path) { fd = unixio_open_socket(path, mode, uid, gid); if (fd < 0) goto error; *cc = ctrlchannel_new(fd, false, path); } else { logprintf(STDERR_FILENO, "Missing path and fd options for UnixIO " "control channel\n"); goto error; } } else if (!strcmp(type, "tcp")) { port = option_get_int(ovs, "port", -1); fd = option_get_int(ovs, "fd", -1); if (fd >= 0) { if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for TCP control channel\n", fd); goto error; } *cc = ctrlchannel_new(fd, false, NULL); } else if (port >= 0) { if (port >= 0x10000) { logprintf(STDERR_FILENO, "TCP control channel port outside valid range\n"); goto error; } bindaddr = option_get_string(ovs, "bindaddr", "127.0.0.1"); ifname = option_get_string(ovs, "ifname", NULL); fd = tcp_open_socket(port, bindaddr, ifname); if (fd < 0) goto error; *cc = ctrlchannel_new(fd, false, NULL); } else { logprintf(STDERR_FILENO, "Missing port and fd options for TCP control channel\n"); goto error; } } else { logprintf(STDERR_FILENO, "Unsupport control channel type: %s\n", type); goto error; } if (*cc == NULL) goto error; option_values_free(ovs); return 0; error: free(error); option_values_free(ovs); return -1; } /* * handle_ctrlchannel_options: * Parse and act upon the parsed 'ctrl' (control channel) options. * * @options: the control channel options to parse * * Returns 0 on success, -1 on failure. */ int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc) { if (!options) return 0; if (parse_ctrlchannel_options(options, cc) < 0) return -1; return 0; } /* * parse_server_options: * Parse the 'server' options. * * @options: the server options to parse * * Returns 0 on success, -1 on failure. */ static int parse_server_options(char *options, struct server **c) { OptionValues *ovs = NULL; char *error = NULL; const char *bindaddr, *ifname; const char *type, *path; int fd, port; struct stat stat; unsigned int flags = 0; mode_t mode; uid_t uid; gid_t gid; *c = NULL; ovs = options_parse(options, server_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing server options: %s\n", error); goto error; } type = option_get_string(ovs, "type", "tcp"); if (option_get_bool(ovs, "disconnect", false)) flags |= SERVER_FLAG_DISCONNECT; if (!strcmp(type, "unixio")) { path = option_get_string(ovs, "path", NULL); fd = option_get_int(ovs, "fd", -1); mode = option_get_mode_t(ovs, "mode", 0770); uid = option_get_uid_t(ovs, "uid", -1); gid = option_get_gid_t(ovs, "gid", -1); if (fd >= 0) { if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for UnixIO control channel\n", fd); goto error; } *c = server_new(fd, flags, NULL); } else if (path) { fd = unixio_open_socket(path, mode, uid, gid); if (fd < 0) goto error; *c = server_new(fd, flags, path); } else { logprintf(STDERR_FILENO, "Missing path and file descriptor option for UnixIO " "socket\n"); goto error; } } else if (!strcmp(type, "tcp")) { fd = option_get_int(ovs, "fd", -1); if (fd >= 0) { if (fstat(fd, &stat) < 0 || !S_ISSOCK(stat.st_mode)) { logprintf(STDERR_FILENO, "Bad filedescriptor %d for TCP socket\n", fd); goto error; } flags |= SERVER_FLAG_FD_GIVEN; *c = server_new(fd, flags, NULL); } else { port = option_get_int(ovs, "port", -1); if (port == -1) { const char *port_str = getenv("TPM_PORT"); if (!port_str || sscanf(port_str, "%d", &port) == -1) port = -1; } if (port < 0) { logprintf(STDERR_FILENO, "No valid port number provided for TCP socket.\n"); goto error; } if (port >= 0x10000) { logprintf(STDERR_FILENO, "TCP socket port outside valid range\n"); goto error; } bindaddr = option_get_string(ovs, "bindaddr", "127.0.0.1"); ifname = option_get_string(ovs, "ifname", NULL); fd = tcp_open_socket(port, bindaddr, ifname); if (fd < 0) goto error; *c = server_new(fd, flags, NULL); } } else { logprintf(STDERR_FILENO, "Unsupport socket type: %s\n", type); goto error; } if (*c == NULL) goto error; option_values_free(ovs); return 0; error: if (*c) { server_free(*c); *c = NULL; } option_values_free(ovs); free(error); return -1; } /* * handle_server_options: * Parse and act upon the parsed 'server' options. * * @options: the server options to parse * * Returns 0 on success, -1 on failure. */ int handle_server_options(char *options, struct server **c) { if (!options) return 0; if (parse_server_options(options, c) < 0) return -1; return 0; } static int parse_locality_options(char *options, uint32_t *flags) { OptionValues *ovs = NULL; char *error = NULL; ovs = options_parse(options, locality_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing locality options: %s\n", error); goto error; } if (option_get_bool(ovs, "reject-locality-4", false)) *flags |= LOCALITY_FLAG_REJECT_LOCALITY_4; if (option_get_bool(ovs, "allow-set-locality", false)) *flags |= LOCALITY_FLAG_ALLOW_SETLOCALITY; option_values_free(ovs); return 0; error: option_values_free(ovs); free(error); return -1; } /* * handle_locality_options: * Parse the 'locality' options. * * @options: the locality options to parse * * Returns 0 on success, -1 on failure. */ int handle_locality_options(char *options, uint32_t *flags) { *flags = 0; if (!options) return 0; if (parse_locality_options(options, flags) < 0) return -1; return 0; } static int parse_flags_options(char *options, bool *need_init_cmd, uint16_t *startupType) { OptionValues *ovs = NULL; char *error = NULL; ovs = options_parse(options, flags_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing flags options: %s\n", error); goto error; } if (option_get_bool(ovs, "not-need-init", false)) *need_init_cmd = false; if (option_get_bool(ovs, "startup-clear", false)) *startupType = TPM_ST_CLEAR; else if (option_get_bool(ovs, "startup-state", false)) *startupType = TPM_ST_STATE; else if (option_get_bool(ovs, "startup-deactivated", false)) *startupType = TPM_ST_DEACTIVATED; else if (option_get_bool(ovs, "startup-none", false)) *startupType = _TPM_ST_NONE; if (*startupType != _TPM_ST_NONE) *need_init_cmd = false; option_values_free(ovs); return 0; error: option_values_free(ovs); free(error); return -1; } /* * handle_flags_options: * Parse the 'flags' options. * * @options: the flags options to parse * * Returns 0 on success, -1 on failure. */ int handle_flags_options(char *options, bool *need_init_cmd, uint16_t *startupType) { if (!options) return 0; if (parse_flags_options(options, need_init_cmd, startupType) < 0) return -1; return 0; } #ifdef WITH_SECCOMP static int parse_seccomp_options(char *options, unsigned int *seccomp_action) { OptionValues *ovs = NULL; char *error = NULL; const char *action; ovs = options_parse(options, seccomp_opt_desc, &error); if (!ovs) { logprintf(STDERR_FILENO, "Error parsing seccomp options: %s\n", error); goto error; } action = option_get_string(ovs, "action", "kill"); if (!strcmp(action, "kill")) { *seccomp_action = SWTPM_SECCOMP_ACTION_KILL; #ifdef SCMP_ACT_LOG } else if (!strcmp(action, "log")) { *seccomp_action = SWTPM_SECCOMP_ACTION_LOG; #endif } else if (!strcmp(action, "none")) { *seccomp_action = SWTPM_SECCOMP_ACTION_NONE; } else { logprintf(STDERR_FILENO, "Unsupported seccomp log action %s\n", action); goto error; } option_values_free(ovs); return 0; error: option_values_free(ovs); free(error); return -1; } /* * handle_seccomp_options: * Parse the 'seccomp' options. * * @options: the flags options to parse * @seccomp_action: the action to take when * * Returns 0 on success, -1 on failure. */ int handle_seccomp_options(char *options, unsigned int *seccomp_action) { *seccomp_action = SWTPM_SECCOMP_ACTION_KILL; if (!options) return 0; if (parse_seccomp_options(options, seccomp_action) < 0) return -1; return 0; } #endif /* WITH_SECCOMP */swtpm-0.6.3/src/swtpm/common.h000066400000000000000000000050671421141172300163000ustar00rootroot00000000000000/* * common.h -- Header file for Common code for swtpm and swtpm_cuse * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_COMMON_H_ #define _SWTPM_COMMON_H_ #include "config.h" #include int handle_log_options(char *options); int handle_key_options(char *options); int handle_migration_key_options(char *options); int handle_pid_options(char *options); int handle_tpmstate_options(char *options); struct ctrlchannel; int handle_ctrlchannel_options(char *options, struct ctrlchannel **cc); struct server; int handle_server_options(char *options, struct server **s); int handle_locality_options(char *options, uint32_t *flags); int handle_flags_options(char *options, bool *need_init_cmd, uint16_t *startupType); #ifdef WITH_SECCOMP int handle_seccomp_options(char *options, unsigned int *seccomp_action); #else static inline int handle_seccomp_options(char *options, unsigned int *seccomp_action) { return 0; } #endif #endif /* _SWTPM_COMMON_H_ */ swtpm-0.6.3/src/swtpm/ctrlchannel.c000066400000000000000000000615761421141172300173070ustar00rootroot00000000000000/* * ctrlchannel.c -- control channel implementation * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "sys_dependencies.h" #include "ctrlchannel.h" #include "logging.h" #include "tpm_ioctl.h" #include "tpmlib.h" #include "swtpm_nvfile.h" #include "locality.h" #include "mainloop.h" #include "utils.h" #include "swtpm_debug.h" /* local variables */ struct ctrlchannel { int fd; int clientfd; char *sockpath; }; struct ctrlchannel *ctrlchannel_new(int fd, bool is_client, const char *sockpath) { struct ctrlchannel *cc = calloc(1, sizeof(struct ctrlchannel)); if (!cc) { logprintf(STDERR_FILENO, "Out of memory"); return NULL; } if (sockpath) { cc->sockpath = strdup(sockpath); if (!cc->sockpath) { logprintf(STDERR_FILENO, "Out of memory"); free(cc); return NULL; } } cc->fd = cc->clientfd = -1; if (is_client) cc->clientfd = fd; else cc->fd = fd; return cc; } int ctrlchannel_get_fd(struct ctrlchannel *cc) { if (!cc) return -1; return cc->fd; } int ctrlchannel_get_client_fd(struct ctrlchannel *cc) { if (!cc) return -1; return cc->clientfd; } int ctrlchannel_set_client_fd(struct ctrlchannel *cc, int fd) { int clientfd; if (!cc) return -1; clientfd = cc->clientfd; cc->clientfd = fd; return clientfd; } static int ctrlchannel_return_state(ptm_getstate *pgs, int fd) { uint32_t blobtype = be32toh(pgs->u.req.type); const char *blobname = tpmlib_get_blobname(blobtype); uint32_t tpm_number = 0; unsigned char *blob = NULL; uint32_t blob_length = 0, return_length; TPM_BOOL is_encrypted = 0; TPM_BOOL decrypt = (be32toh(pgs->u.req.state_flags) & PTM_STATE_FLAG_DECRYPTED) != 0; TPM_RESULT res = 0; uint32_t offset = be32toh(pgs->u.req.offset); ptm_getstate pgs_res; uint32_t state_flags; struct iovec iov[2]; int iovcnt, n; if (blobtype == PTM_BLOB_TYPE_VOLATILE) res = SWTPM_NVRAM_Store_Volatile(); if (res == 0) res = SWTPM_NVRAM_GetStateBlob(&blob, &blob_length, tpm_number, blobname, decrypt, &is_encrypted); /* make sure the volatile state file is gone */ if (blobtype == PTM_BLOB_TYPE_VOLATILE) SWTPM_NVRAM_DeleteName(tpm_number, blobname, FALSE); if (offset < blob_length) { return_length = blob_length - offset; } else { return_length = 0; } state_flags = (is_encrypted) ? PTM_STATE_FLAG_ENCRYPTED : 0; pgs_res.u.resp.tpm_result = htobe32(res); pgs_res.u.resp.state_flags = htobe32(state_flags); pgs_res.u.resp.totlength = htobe32(return_length); pgs_res.u.resp.length = htobe32(return_length); iov[0].iov_base = &pgs_res; iov[0].iov_len = offsetof(ptm_getstate, u.resp.data); iovcnt = 1; SWTPM_PrintAll(" Ctrl Rsp:", " ", iov[0].iov_base, iov[0].iov_len); if (res == 0 && return_length) { iov[1].iov_base = &blob[offset]; iov[1].iov_len = return_length; iovcnt = 2; SWTPM_PrintAll(" Ctrl Rsp Continued:", " ", iov[1].iov_base, min(iov[1].iov_len, 1024)); } n = writev_full(fd, iov, iovcnt); if (n < 0) { logprintf(STDERR_FILENO, "Error: Could not send response: %s\n", strerror(errno)); close(fd); fd = -1; } free(blob); return fd; } static int ctrlchannel_receive_state(ptm_setstate *pss, ssize_t n, int fd) { uint32_t blobtype = be32toh(pss->u.req.type); uint32_t tpm_number = 0; unsigned char *blob = NULL; uint32_t blob_length = be32toh(pss->u.req.length); uint32_t remain = blob_length, offset = 0; TPM_RESULT res; uint32_t flags = be32toh(pss->u.req.state_flags); TPM_BOOL is_encrypted = (flags & PTM_STATE_FLAG_ENCRYPTED) != 0; blob = malloc(blob_length); if (!blob) { logprintf(STDERR_FILENO, "Could not allocated %u bytes.\n", blob_length); res = TPM_FAIL; goto err_send_resp; } n -= offsetof(ptm_setstate, u.req.data); /* n holds the number of available data bytes */ while (true) { if (n < 0 || (uint32_t)n > remain) { res = TPM_BAD_PARAMETER; goto err_send_resp; } memcpy(&blob[offset], pss->u.req.data, n); offset += n; remain -= n; if (remain) { n = read_eintr(fd, pss->u.req.data, sizeof(pss->u.req.data)); if (n < 0) { res = TPM_IOERROR; close(fd); fd = -1; goto err_fd_broken; } else if (n == 0) { res = TPM_BAD_PARAMETER; goto err_send_resp; } } else { break; } } res = SWTPM_NVRAM_SetStateBlob(blob, blob_length, is_encrypted, tpm_number, blobtype); err_send_resp: pss->u.resp.tpm_result = htobe32(res); n = write_full(fd, pss, sizeof(pss->u.resp.tpm_result)); if (n < 0) { logprintf(STDERR_FILENO, "Error: Could not send response: %s\n", strerror(errno)); close(fd); fd = -1; } err_fd_broken: free(blob); return fd; } /* timespec_diff: calculate difference between two timespecs * * @end: end time * @start: start time; must be earlier than @end * @diff: result * * This function will return a negative tv_sec in result, if * @end is earlier than @start, the time difference otherwise. */ static void timespec_diff(struct timespec *end, struct timespec *start, struct timespec *diff) { diff->tv_nsec = end->tv_nsec - start->tv_nsec; diff->tv_sec = end->tv_sec - start->tv_sec; if (diff->tv_nsec < 0) { diff->tv_nsec += 1E9; diff->tv_sec -= 1; } } struct input { uint32_t cmd; /* ptm_hdata is the largest buffer to receive */ uint8_t body[sizeof(ptm_hdata)]; }; /* * ctrlchannel_recv_cmd: Receive a command on the control channel * * @fd: file descriptor for control channel * @msg: prepared msghdr struct for receiveing data with single * msg_iov. * * This function returns 0 or a negative number if an error receiving * the command occurred, including a timeout. In case of success, * the nunber of bytes received is returned. */ static ssize_t ctrlchannel_recv_cmd(int fd, struct msghdr *msg) { ssize_t n; size_t recvd = 0; size_t needed = offsetof(struct input, body); struct input *input = (struct input *)msg->msg_iov[0].iov_base; struct pollfd pollfd = { .fd = fd, .events = POLLIN, }; struct timespec deadline, now, timeout; int to; size_t buffer_len = msg->msg_iov[0].iov_len; /* Read-write */ ptm_init *init_p; ptm_reset_est *pre; ptm_hdata *phd; ptm_getstate *pgs; ptm_setstate *pss; ptm_loc *pl; const void *msg_iov = msg->msg_iov; clock_gettime(CLOCK_REALTIME, &deadline); /* maximum allowed time is 500ms to receive everything */ deadline.tv_nsec += 500 * 1E6; if (deadline.tv_nsec >= 1E9) { deadline.tv_nsec -= 1E9; deadline.tv_sec += 1; } while (recvd < buffer_len) { if (!recvd) { n = recvmsg(fd, msg, 0); /* address a coverity issue by validating msg */ if (msg_iov != msg->msg_iov || msg->msg_iov[0].iov_base != input || msg->msg_iov[0].iov_len > buffer_len) return -1; } else n = read_eintr(fd, msg->msg_iov[0].iov_base + recvd, buffer_len - recvd); if (n <= 0) return n; recvd += n; /* we need to at least see the cmd */ if (recvd < offsetof(struct input, body)) goto wait_chunk; switch (be32toh(input->cmd)) { case CMD_GET_CAPABILITY: break; case CMD_INIT: needed = offsetof(struct input, body) + sizeof(init_p->u.req); break; case CMD_SHUTDOWN: break; case CMD_GET_TPMESTABLISHED: break; case CMD_SET_LOCALITY: needed = offsetof(struct input, body) + sizeof(pl->u.req); break; case CMD_HASH_START: break; case CMD_HASH_DATA: needed = offsetof(struct input, body) + offsetof(struct ptm_hdata, u.req.data); if (recvd >= needed) { phd = (struct ptm_hdata *)&input->body; needed += be32toh(phd->u.req.length); } break; case CMD_HASH_END: break; case CMD_CANCEL_TPM_CMD: break; case CMD_STORE_VOLATILE: break; case CMD_RESET_TPMESTABLISHED: needed = offsetof(struct input, body) + sizeof(pre->u.req); break; case CMD_GET_STATEBLOB: needed = offsetof(struct input, body) + sizeof(pgs->u.req); break; case CMD_SET_STATEBLOB: needed = offsetof(struct input, body) + offsetof(struct ptm_setstate, u.req.data); if (recvd >= needed) { pss = (struct ptm_setstate *)&input->body; needed += be32toh(pss->u.req.length); } break; case CMD_STOP: break; case CMD_GET_CONFIG: break; case CMD_SET_BUFFERSIZE: break; } if (recvd >= needed) break; wait_chunk: clock_gettime(CLOCK_REALTIME, &now); timespec_diff(&deadline, &now, &timeout); if (timeout.tv_sec < 0) break; to = timeout.tv_sec * 1000 + timeout.tv_nsec / 1E6; /* wait for the next chunk */ while (true) { n = poll(&pollfd, 1, to); if (n < 0 && errno == EINTR) continue; if (n <= 0) return n; break; } /* we should have data now */ } return recvd; } static uint64_t get_ptm_caps_supported(TPMLIB_TPMVersion tpmversion) { uint64_t caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | PTM_CAP_SET_LOCALITY | PTM_CAP_HASHING | PTM_CAP_CANCEL_TPM_CMD | PTM_CAP_STORE_VOLATILE | PTM_CAP_RESET_TPMESTABLISHED | PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | PTM_CAP_STOP | PTM_CAP_GET_CONFIG #ifndef __CYGWIN__ | PTM_CAP_SET_DATAFD #endif | PTM_CAP_SET_BUFFERSIZE | PTM_CAP_GET_INFO; if (tpmversion == TPMLIB_TPM_VERSION_2) caps |= PTM_CAP_SEND_COMMAND_HEADER; return caps; } /* * ctrlchannel_process_fd: Read command from control channel and execute it * * @fd: file descriptor for control channel * @terminate: pointer to a boolean that will be set to true by this * function in case the process should shut down; CMD_SHUTDOWN * will set this * @locality: pointer to locality identifier that must point to the global * locality variable and that will receive the new locality * number when set via CMD_SET_LOCALITY * @tpm_running: indicates whether the TPM is running; may be changed by * this function in case TPM is stopped or started * @mlp: mainloop parameters used; may be altered by this function incase of * CMD_SET_DATAFD * @tpmversion: the emulated TPM's version * * This function returns the passed file descriptor or -1 in case the * file descriptor was closed. */ int ctrlchannel_process_fd(int fd, bool *terminate, TPM_MODIFIER_INDICATOR *locality, bool *tpm_running, struct mainLoopParams *mlp) { struct input input = {0, }; struct output { uint8_t body[sizeof(struct ptm_hdata)]; /* ptm_hdata is largest */ } output; ssize_t n; struct iovec iov = { .iov_base = &input, .iov_len = sizeof(input), }; char control[CMSG_SPACE(sizeof(int))]; struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, .msg_control = control, .msg_controllen = sizeof(control), }; struct cmsghdr *cmsg = NULL; int *data_fd = NULL; /* Write-only */ ptm_cap *ptm_caps = (ptm_cap *)&output.body; ptm_res *res_p = (ptm_res *)&output.body; ptm_est *te = (ptm_est *)&output.body; ptm_getconfig *pgc = (ptm_getconfig *)&output.body; /* Read-write */ ptm_init *init_p; ptm_reset_est *re; ptm_hdata *data; ptm_getstate *pgs; ptm_setstate *pss; ptm_loc *pl; ptm_setbuffersize *psbs; ptm_getinfo *pgi, _pgi; size_t out_len = 0; TPM_RESULT res; uint32_t remain; uint32_t buffersize, maxsize, minsize; uint64_t info_flags; uint32_t offset; char *info_data = NULL; size_t length; TPM_MODIFIER_INDICATOR orig_locality; if (fd < 0) return -1; n = ctrlchannel_recv_cmd(fd, &msg); if (n <= 0) { goto err_socket; } SWTPM_PrintAll(" Ctrl Cmd:", " ", msg.msg_iov->iov_base, min(n, 1024)); if ((size_t)n < sizeof(input.cmd)) { goto err_bad_input; } n -= sizeof(input.cmd); switch (be32toh(input.cmd)) { case CMD_GET_CAPABILITY: *ptm_caps = htobe64(get_ptm_caps_supported(mlp->tpmversion)); out_len = sizeof(*ptm_caps); break; case CMD_INIT: if (n != (ssize_t)sizeof(ptm_init)) /* r/w */ goto err_bad_input; init_p = (ptm_init *)input.body; TPMLIB_Terminate(); *tpm_running = false; res = tpmlib_start(be32toh(init_p->u.req.init_flags), mlp->tpmversion); if (res) { logprintf(STDERR_FILENO, "Error: Could not initialize the TPM\n"); } else { *tpm_running = true; } *res_p = htobe32(res); out_len = sizeof(ptm_res); break; case CMD_STOP: if (n != 0) /* wo */ goto err_bad_input; TPMLIB_Terminate(); *tpm_running = false; *res_p = htobe32(TPM_SUCCESS); out_len = sizeof(ptm_res); break; case CMD_SHUTDOWN: if (n != 0) /* wo */ goto err_bad_input; TPMLIB_Terminate(); *res_p = htobe32(TPM_SUCCESS); out_len = sizeof(ptm_res); *terminate = true; break; case CMD_GET_TPMESTABLISHED: if (!*tpm_running) goto err_not_running; if (n != 0) /* wo */ goto err_bad_input; out_len = sizeof(te->u.resp); memset(output.body, 0, out_len); res = htobe32(TPM_IO_TpmEstablished_Get(&te->u.resp.bit)); te->u.resp.tpm_result = res; break; case CMD_RESET_TPMESTABLISHED: if (!*tpm_running) goto err_not_running; if (n < (ssize_t)sizeof(re->u.req.loc)) /* rw */ goto err_bad_input; re = (ptm_reset_est *)input.body; if (re->u.req.loc > 4) { res = htobe32(TPM_BAD_LOCALITY); } else { orig_locality = *locality; *locality = re->u.req.loc; res = htobe32(TPM_IO_TpmEstablished_Reset()); *locality = orig_locality; } *res_p = res; out_len = sizeof(re->u.resp); break; case CMD_SET_LOCALITY: if (n < (ssize_t)sizeof(pl->u.req.loc)) /* rw */ goto err_bad_input; pl = (ptm_loc *)input.body; if (pl->u.req.loc > 4 || (pl->u.req.loc == 4 && mlp->locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) { res = TPM_BAD_LOCALITY; } else { res = TPM_SUCCESS; *locality = pl->u.req.loc; } *res_p = htobe32(res); out_len = sizeof(re->u.resp); break; case CMD_HASH_START: if (!*tpm_running) goto err_not_running; if (n != 0) /* wo */ goto err_bad_input; *res_p = htobe32(TPM_IO_Hash_Start()); out_len = sizeof(ptm_res); break; case CMD_HASH_DATA: if (!*tpm_running) goto err_not_running; if (n < (ssize_t)offsetof(ptm_hdata, u.req.data)) /* rw */ goto err_bad_input; data = (ptm_hdata *)&input.body; remain = htobe32(data->u.req.length); n -= sizeof(data->u.req.length); /* n has the available number of bytes to hash */ while (true) { res = TPM_IO_Hash_Data(data->u.req.data, n); if (res) break; remain -= n; if (!remain) break; n = read_eintr(fd, &data->u.req.data, sizeof(data->u.req.data)); if (n <= 0) { res = TPM_IOERROR; break; } } data = (ptm_hdata *)&output.body; data->u.resp.tpm_result = htobe32(res); out_len = sizeof(data->u.resp.tpm_result); break; case CMD_HASH_END: if (!*tpm_running) goto err_not_running; if (n != 0) /* wo */ goto err_bad_input; *res_p = htobe32(TPM_IO_Hash_End()); out_len = sizeof(ptm_res); break; case CMD_CANCEL_TPM_CMD: if (!*tpm_running) goto err_not_running; if (n != 0) /* wo */ goto err_bad_input; /* for cancellation to work, the TPM would have to * execute in another thread that polls on a cancel * flag */ *res_p = htobe32(TPMLIB_CancelCommand()); out_len = sizeof(ptm_res); break; case CMD_STORE_VOLATILE: if (!*tpm_running) goto err_not_running; if (n != 0) /* wo */ goto err_bad_input; *res_p = htobe32(SWTPM_NVRAM_Store_Volatile()); out_len = sizeof(ptm_res); break; case CMD_GET_STATEBLOB: if (!*tpm_running) goto err_not_running; pgs = (ptm_getstate *)input.body; if (n < (ssize_t)sizeof(pgs->u.req)) /* rw */ goto err_bad_input; return ctrlchannel_return_state(pgs, fd); case CMD_SET_STATEBLOB: if (*tpm_running) goto err_running; /* tpm state dir must be set */ SWTPM_NVRAM_Init(); pss = (ptm_setstate *)input.body; if (n < (ssize_t)offsetof(ptm_setstate, u.req.data)) /* rw */ goto err_bad_input; return ctrlchannel_receive_state(pss, n, fd); case CMD_GET_CONFIG: if (n != 0) /* wo */ goto err_bad_input; pgc->u.resp.tpm_result = htobe32(0); pgc->u.resp.flags = htobe32(0); if (SWTPM_NVRAM_Has_FileKey()) pgc->u.resp.flags |= htobe32(PTM_CONFIG_FLAG_FILE_KEY); if (SWTPM_NVRAM_Has_MigrationKey()) pgc->u.resp.flags |= htobe32(PTM_CONFIG_FLAG_MIGRATION_KEY); out_len = sizeof(pgc->u.resp); break; case CMD_SET_DATAFD: #ifdef __CYGWIN__ if (1) goto err_running; #endif if (mlp->fd != -1) goto err_io; cmsg = CMSG_FIRSTHDR(&msg); if (!cmsg || cmsg->cmsg_len < CMSG_LEN(sizeof(int)) || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS || !(data_fd = (int *)CMSG_DATA(cmsg)) || *data_fd < 0) { logprintf(STDERR_FILENO, "no valid data socket in message; cmsg = " "%p", cmsg); goto err_bad_input; } mlp->flags = MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION | MAIN_LOOP_FLAG_END_ON_HUP; mlp->fd = *data_fd; *res_p = htobe32(TPM_SUCCESS); out_len = sizeof(ptm_res); break; case CMD_SET_BUFFERSIZE: psbs = (ptm_setbuffersize *)input.body; if (n < (ssize_t)sizeof(psbs->u.req)) /* rw */ goto err_bad_input; buffersize = be32toh(psbs->u.req.buffersize); if (buffersize > 0 && *tpm_running) goto err_running; buffersize = TPMLIB_SetBufferSize(buffersize, &minsize, &maxsize); *res_p = htobe32(TPM_SUCCESS); psbs = (ptm_setbuffersize *)&output.body; out_len = sizeof(psbs->u.resp); psbs->u.resp.buffersize = htobe32(buffersize); psbs->u.resp.minsize = htobe32(minsize); psbs->u.resp.maxsize = htobe32(maxsize); break; case CMD_GET_INFO: if (n < (ssize_t)sizeof(pgi->u.req)) /* rw */ goto err_bad_input; /* copy since flags needs to be 8-byte aligned */ memcpy(&_pgi, input.body, sizeof(_pgi)); pgi = &_pgi; info_flags = be64toh(pgi->u.req.flags); info_data = TPMLIB_GetInfo(info_flags); if (!info_data) goto err_memory; offset = be32toh(pgi->u.req.offset); if (offset >= strlen(info_data)) { free(info_data); goto err_bad_input; } length = min(strlen(info_data) + 1 - offset, sizeof(pgi->u.resp.buffer)); pgi = (ptm_getinfo *)&output.body; pgi->u.resp.tpm_result = htobe32(0); pgi->u.resp.totlength = htobe32(strlen(info_data) + 1); pgi->u.resp.length = htobe32(length); /* client has to collect whole string in case buffer is too small */ memcpy(pgi->u.resp.buffer, &info_data[offset], length); free(info_data); out_len = offsetof(ptm_getinfo, u.resp.buffer) + length; break; default: logprintf(STDERR_FILENO, "Error: Unknown command: 0x%08x\n", be32toh(input.cmd)); *res_p = htobe32(TPM_BAD_ORDINAL); out_len = sizeof(ptm_res); } send_resp: SWTPM_PrintAll(" Ctrl Rsp:", " ", output.body, min(out_len, 1024)); n = write_full(fd, output.body, out_len); if (n < 0) { logprintf(STDERR_FILENO, "Error: Could not send response: %s\n", strerror(errno)); close(fd); fd = -1; } return fd; err_bad_input: *res_p = htobe32(TPM_BAD_PARAMETER); out_len = sizeof(ptm_res); goto send_resp; err_running: err_not_running: *res_p = htobe32(TPM_BAD_ORDINAL); out_len = sizeof(ptm_res); goto send_resp; err_io: *res_p = htobe32(TPM_IOERROR); out_len = sizeof(ptm_res); goto send_resp; err_memory: *res_p = htobe32(TPM_SIZE); out_len = sizeof(ptm_res); goto send_resp; err_socket: close(fd); return -1; } void ctrlchannel_free(struct ctrlchannel *cc) { if (!cc) return; if (cc->fd >= 0) close(cc->fd); if (cc->clientfd >= 0) close(cc->clientfd); if (cc->sockpath) { unlink(cc->sockpath); free(cc->sockpath); } free(cc); } swtpm-0.6.3/src/swtpm/ctrlchannel.h000066400000000000000000000046431421141172300173040ustar00rootroot00000000000000/* * ctrlchannel.h -- control channel implementation * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_CTRLCHANNEL_H_ #define _SWTPM_CTRLCHANNEL_H_ #include #include struct ctrlchannel; struct libtpms_callbacks; struct mainLoopParams; struct ctrlchannel *ctrlchannel_new(int fd, bool isclient, const char *sockpath); int ctrlchannel_get_fd(struct ctrlchannel *cc); int ctrlchannel_get_client_fd(struct ctrlchannel *cc); int ctrlchannel_set_client_fd(struct ctrlchannel *cc, int fd); int ctrlchannel_process_fd(int fd, bool *terminate, TPM_MODIFIER_INDICATOR *locality, bool *tpm_running, struct mainLoopParams *mlp); void ctrlchannel_free(struct ctrlchannel *cc); #endif /* _SWTPM_CTRLCHANNEL_H_ */ swtpm-0.6.3/src/swtpm/cuse_tpm.c000066400000000000000000001446621421141172300166270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* CUSE TPM */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2014-2015. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* * Authors: * Eric Richter, erichte@us.ibm.com * Stefan Berger, stefanb@us.ibm.com * David Safford, safford@us.ibm.com */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swtpm.h" #include "common.h" #include "tpmstate.h" #include "pidfile.h" #include "locality.h" #include "logging.h" #include "tpm_ioctl.h" #include "swtpm_nvfile.h" #include "tpmlib.h" #include "main.h" #include "utils.h" #include "threadpool.h" #include "seccomp_profile.h" #include "options.h" #include "capabilities.h" /* maximum size of request buffer */ #define TPM_REQ_MAX 4096 /* version of the TPM (1.2 or 2) */ static TPMLIB_TPMVersion tpmversion; /* buffer containing the TPM request */ static unsigned char *ptm_request; /* buffer containing the TPM response */ static unsigned char *ptm_response; /* offset from where to read from; reset when ptm_response is set */ static size_t ptm_read_offset; /* the sizes of the data in the buffers */ static uint32_t ptm_req_len, ptm_res_len, ptm_res_tot; /* locality applied to TPM commands */ static TPM_MODIFIER_INDICATOR locality; /* whether the TPM is running (TPM_Init was received) */ static bool tpm_running; /* flags on how to handle locality */ static uint32_t locality_flags; /* the fuse_session that we will signal an exit to to exit the prg. */ static struct fuse_session *ptm_fuse_session; #if GLIB_MAJOR_VERSION >= 2 # if GLIB_MINOR_VERSION >= 32 static GMutex file_ops_lock; # define FILE_OPS_LOCK &file_ops_lock # else static GMutex *file_ops_lock; # define FILE_OPS_LOCK file_ops_lock # endif #else #error Unsupport glib version #endif struct cuse_param { char *runas; char *logging; char *keydata; char *migkeydata; char *piddata; char *tpmstatedata; char *localitydata; char *seccompdata; unsigned int seccomp_action; char *flagsdata; uint16_t startupType; }; /* single message to send to the worker thread */ static struct thread_message msg; struct stateblob { uint8_t type; uint8_t *data; uint32_t length; TPM_BOOL is_encrypted; }; typedef struct stateblob_desc { uint32_t blobtype; TPM_BOOL decrypt; TPM_BOOL is_encrypted; unsigned char *data; uint32_t data_length; } stateblob_desc; typedef enum tx_state_type { TX_STATE_RW_COMMAND = 1, TX_STATE_SET_STATE_BLOB = 2, TX_STATE_GET_STATE_BLOB = 3, } tx_state_type; typedef struct transfer_state { tx_state_type state; /* while in TX_STATE_GET/SET_STATEBLOB */ uint32_t blobtype; TPM_BOOL blob_is_encrypted; /* while in TX_STATE_GET */ uint32_t offset; } transfer_state; typedef struct TPM_Response_Header { uint16_t tag; uint32_t paramSize; uint32_t returnCode; } __attribute__ ((packed)) TPM_Response_Header; /*********************************** data *************************************/ static const char *usage = "usage: %s %s [options]\n" "\n" "The following options are supported:\n" "\n" "-n NAME|--name=NAME : device name (mandatory)\n" "-M MAJ|--maj=MAJ : device major number\n" "-m MIN|--min=MIN : device minor number\n" "--key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " files; use the given mode for the block encryption;\n" " the key is to be provided as a hex string or in binary\n" " format; the keyfile can be automatically removed using\n" " the remove parameter\n" "--key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--locality [reject-locality-4][,allow-set-locality]\n" " : reject-locality-4: reject any command in locality 4\n" " allow-set-locality: accept SetLocality command\n" "--migration-key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " when it is retrieved from the TPM via ioctls;\n" " Setting this key ensures that the TPM's state will always\n" " be encrypted when migrated\n" "--migration-key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--log file=|fd=[,level=n][,prefix=][,truncate]\n" " : write the TPM's log into the given file rather than\n" " to the console; provide '-' for path to avoid logging\n" " log level 5 and higher will enable libtpms logging;\n" " all logged output will be prefixed with prefix;\n" " the log file can be reset (truncate)\n" "--pid file=|fd=\n" " : write the process ID into the given file\n" "--tpmstate dir=[,mode=0...]\n" " : set the directory where the TPM's state will be written\n" " into; the TPM_PATH environment variable can be used\n" " instead;\n" " mode allows a user to set the file mode bits of the state\n" " files; the default mode is 0640;\n" "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel;\n" " startup-...: send Startup command with this type;\n" "-r|--runas : after creating the CUSE device, change to the given\n" " user\n" "--tpm2 : choose TPM2 functionality\n" #ifdef WITH_SECCOMP # ifndef SCMP_ACT_LOG "--seccomp action=none|kill\n" # else "--seccomp action=none|kill|log\n" # endif " : Choose the action of the seccomp profile when a\n" " blacklisted syscall is executed; default is kill\n" #endif "--print-capabilites : print capabilities and terminate\n" "-h|--help : display this help screen and terminate\n" "\n"; static TPM_RESULT ptm_io_getlocality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum) { *loc = locality; return TPM_SUCCESS; } static struct libtpms_callbacks cbs = { .sizeOfStruct = sizeof(struct libtpms_callbacks), .tpm_nvram_init = SWTPM_NVRAM_Init, .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData, .tpm_nvram_storedata = SWTPM_NVRAM_StoreData, .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName, .tpm_io_getlocality = ptm_io_getlocality, }; /* the current state the transfer interface is in */ static transfer_state tx_state; /* function prototypes */ static void ptm_cleanup(void); /************************* cached stateblob *********************************/ static stateblob_desc cached_stateblob; /* * cached_stateblob_is_loaded: is the stateblob with the given properties * the one in the cache? */ static bool cached_stateblob_is_loaded(uint32_t blobtype, TPM_BOOL decrypt) { return (cached_stateblob.data != NULL) && (cached_stateblob.blobtype == blobtype) && (cached_stateblob.decrypt == decrypt); } /* * cached_stateblob_free: Free any previously loaded state blob */ static void cached_stateblob_free(void) { free(cached_stateblob.data); cached_stateblob.data = NULL; cached_stateblob.data_length = 0; } /* * cached_stateblob_get_bloblength: get the total length of the cached blob */ static uint32_t cached_stateblob_get_bloblength(void) { return cached_stateblob.data_length; } /* * cached_statblob_get: get stateblob data without copying them * * @offset: at which offset to get the data * @bufptr: pointer to a buffer pointer used to return buffer start * @length: pointer used to return number of available bytes in returned buffer */ static int cached_stateblob_get(uint32_t offset, unsigned char **bufptr, size_t *length) { if (cached_stateblob.data == NULL || offset > cached_stateblob.data_length) return -1; *bufptr = &cached_stateblob.data[offset]; *length = cached_stateblob.data_length - offset; return 0; } /* * cached_stateblob_load: load a state blob into the cache * * blobtype: the type of blob * decrypt: whether the blob is to be decrypted */ static TPM_RESULT cached_stateblob_load(uint32_t blobtype, TPM_BOOL decrypt) { TPM_RESULT res = 0; const char *blobname = tpmlib_get_blobname(blobtype); uint32_t tpm_number = 0; if (!blobname) return TPM_BAD_PARAMETER; cached_stateblob_free(); if (blobtype == PTM_BLOB_TYPE_VOLATILE) res = SWTPM_NVRAM_Store_Volatile(); if (res == 0) res = SWTPM_NVRAM_GetStateBlob(&cached_stateblob.data, &cached_stateblob.data_length, tpm_number, blobname, decrypt, &cached_stateblob.is_encrypted); /* make sure the volatile state file is gone */ if (blobtype == PTM_BLOB_TYPE_VOLATILE) SWTPM_NVRAM_DeleteName(tpm_number, blobname, FALSE); if (res == 0) { cached_stateblob.blobtype = blobtype; cached_stateblob.decrypt = decrypt; } return res; } /* * cached_state_blob_copy: copy the cached state blob to a destination buffer * * dest: destination buffer * destlen: size of the buffer * srcoffset: offset to copy from * copied: variable to return the number of copied bytes * is_encrypted: variable to return whether the blob is encrypted */ static int cached_stateblob_copy(void *dest, size_t destlen, uint32_t srcoffset, uint32_t *copied, TPM_BOOL *is_encrypted) { int ret = -1; *copied = 0; if (cached_stateblob.data != NULL && cached_stateblob.data_length > 0) { if (srcoffset < cached_stateblob.data_length) { *copied = min(cached_stateblob.data_length - srcoffset, destlen); memcpy(dest, &cached_stateblob.data[srcoffset], *copied); *is_encrypted = cached_stateblob.is_encrypted; } ret = 0; } return ret; } /************************* worker thread ************************************/ /* * worker_thread: the worker thread */ static void worker_thread(gpointer data, gpointer user_data) { struct thread_message *msg = (struct thread_message *)data; switch (msg->type) { case MESSAGE_TPM_CMD: TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot, ptm_request, ptm_req_len); ptm_read_offset = 0; break; case MESSAGE_IOCTL: break; } /* results are ready */ worker_thread_mark_done(); } /***************************** utility functions ****************************/ /* * tpm_start: Start the TPM * * Check whether the TPM's state directory exists and if it does * not exists, try to creat it. Start the thread pool, initilize * libtpms and allocate a global TPM request buffer. * * @flags: libtpms init flags * @l_tpmversion: the version of the TPM * @res: the result from starting the TPM */ static int tpm_start(uint32_t flags, TPMLIB_TPMVersion l_tpmversion, TPM_RESULT *res) { DIR *dir; const char *tpmdir = tpmstate_get_dir(); *res = TPM_FAIL; dir = opendir(tpmdir); if (dir) { closedir(dir); } else { if (mkdir(tpmdir, 0775)) { logprintf(STDERR_FILENO, "Error: Could not open tpmstate dir %s\n", tpmdir); return -1; } } pool = g_thread_pool_new(worker_thread, NULL, 1, FALSE, NULL); if (!pool) { logprintf(STDERR_FILENO, "Error: Could not create the thread pool.\n"); return -1; } if(!ptm_request) ptm_request = malloc(4096); if(!ptm_request) { logprintf(STDERR_FILENO, "Error: Could not allocate memory for request buffer.\n"); goto error_del_pool; } *res = tpmlib_start(flags, l_tpmversion); if (*res != TPM_SUCCESS) goto error_del_pool; logprintf(STDOUT_FILENO, "CUSE TPM successfully initialized.\n"); return 0; error_del_pool: g_thread_pool_free(pool, TRUE, TRUE); pool = NULL; return -1; } /* * ptm_write_fatal_error_response: Write fatal error response * * Write a fatal error response into the global ptm_response buffer. */ static void ptm_write_fatal_error_response(TPMLIB_TPMVersion l_tpmversion) { tpmlib_write_fatal_error_response(&ptm_response, &ptm_res_len, &ptm_res_tot, l_tpmversion); ptm_read_offset = 0; } /* * ptm_send_startup: Send a TPM/TPM2_Startup */ static int ptm_send_startup(uint16_t startupType, TPMLIB_TPMVersion l_tpmversion) { uint32_t command_length; unsigned char command[sizeof(struct tpm_startup)]; uint32_t max_command_length = sizeof(command); int ret = 0; TPM_RESULT rc = TPM_SUCCESS; command_length = tpmlib_create_startup_cmd( startupType, tpmversion, command, max_command_length); if (command_length > 0) { rc = TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot, (unsigned char *)command, command_length); ptm_read_offset = 0; } if (rc || command_length == 0) { if (rc) { logprintf(STDERR_FILENO, "Could not send Startup: 0x%x\n", rc); ret = -1; } } return ret; } /************************************ read() support ***************************/ /* * ptm_read_result: Return the TPM response packet * * @req: the fuse_req_t * @size: the max. number of bytes to return to the requester */ static void ptm_read_result(fuse_req_t req, size_t size) { size_t len = 0; if (tpm_running) { /* wait until results are ready */ worker_thread_wait_done(); } if (ptm_read_offset < ptm_res_len) { len = ptm_res_len - ptm_read_offset; if (size < len) len = size; } fuse_reply_buf(req, (const char *)&ptm_response[ptm_read_offset], len); ptm_read_offset += len; } /* * ptm_read_stateblob: get a TPM stateblob via the read() interface * * @req: the fuse_req_t * @size: the number of bytes to read * * The internal offset into the buffer is advanced by the number * of bytes that were copied. We switch back to command read/write * mode if an error occurred or once all bytes were read. */ static void ptm_read_stateblob(fuse_req_t req, size_t size) { unsigned char *bufptr = NULL; size_t numbytes; size_t tocopy; if (cached_stateblob_get(tx_state.offset, &bufptr, &numbytes) < 0) { fuse_reply_err(req, EIO); tx_state.state = TX_STATE_RW_COMMAND; } else { tocopy = MIN(size, numbytes); tx_state.offset += tocopy; fuse_reply_buf(req, (char *)bufptr, tocopy); /* last transfer indicated by less bytes available than requested */ if (numbytes < size) { tx_state.state = TX_STATE_RW_COMMAND; } } } /* * ptm_read: interface to POSIX read() * * @req: fuse_req_t * @size: number of bytes to read * @off: offset (not used) * @fi: fuse_file_info (not used) * * Depending on the current state of the transfer interface (read/write) * return either the results of TPM commands or a data of a TPM state blob. */ static void ptm_read(fuse_req_t req, size_t size, off_t off, struct fuse_file_info *fi) { switch (tx_state.state) { case TX_STATE_RW_COMMAND: ptm_read_result(req, size); break; case TX_STATE_SET_STATE_BLOB: fuse_reply_err(req, EIO); tx_state.state = TX_STATE_RW_COMMAND; break; case TX_STATE_GET_STATE_BLOB: ptm_read_stateblob(req, size); break; } } /*************************read/write stateblob support ***********************/ /* * ptm_set_stateblob_append: Append a piece of TPM state blob and transfer to TPM * * blobtype: the type of blob * data: the data to append * length: length of the data * is_encrypted: whether the blob is encrypted * is_last: whether this is the last part of the TPM state blob; if it is, the TPM * state blob will then be transferred to the TPM */ static TPM_RESULT ptm_set_stateblob_append(uint32_t blobtype, const unsigned char *data, uint32_t length, bool is_encrypted, bool is_last) { TPM_RESULT res = 0; static struct stateblob stateblob; unsigned char *tmp; if (stateblob.type != blobtype) { /* new blob; clear old data */ free(stateblob.data); stateblob.data = NULL; stateblob.length = 0; stateblob.type = blobtype; stateblob.is_encrypted = is_encrypted; /* * on the first call for a new state blob we allow 0 bytes to be written * this allows the user to transfer via write() */ if (length == 0) return 0; } /* append */ tmp = realloc(stateblob.data, stateblob.length + length); if (!tmp) { logprintf(STDERR_FILENO, "Could not allocate %u bytes.\n", stateblob.length + length); /* error */ free(stateblob.data); stateblob.data = NULL; stateblob.length = 0; stateblob.type = 0; return TPM_FAIL; } else stateblob.data = tmp; memcpy(&stateblob.data[stateblob.length], data, length); stateblob.length += length; if (!is_last) { /* full packet -- expecting more data */ return res; } res = SWTPM_NVRAM_SetStateBlob(stateblob.data, stateblob.length, stateblob.is_encrypted, 0 /* tpm_number */, blobtype); logprintf(STDERR_FILENO, "Deserialized state type %d (%s), length=%d, res=%d\n", blobtype, tpmlib_get_blobname(blobtype), stateblob.length, res); free(stateblob.data); stateblob.data = NULL; stateblob.length = 0; stateblob.type = 0; /* transfer of blob is complete */ tx_state.state = TX_STATE_RW_COMMAND; return res; } /* * ptm_set_stateblob: set part of a TPM state blob * * @req: fuse_req_t * pss: ptm_setstate provided via ioctl() */ static void ptm_set_stateblob(fuse_req_t req, ptm_setstate *pss) { TPM_RESULT res = 0; TPM_BOOL is_encrypted = ((pss->u.req.state_flags & PTM_STATE_FLAG_ENCRYPTED) != 0); bool is_last = (sizeof(pss->u.req.data) != pss->u.req.length); if (pss->u.req.length > sizeof(pss->u.req.data)) { res = TPM_BAD_PARAMETER; goto send_response; } /* transfer of blob initiated */ tx_state.state = TX_STATE_SET_STATE_BLOB; tx_state.blobtype = pss->u.req.type; tx_state.blob_is_encrypted = is_encrypted; tx_state.offset = 0; res = ptm_set_stateblob_append(pss->u.req.type, pss->u.req.data, pss->u.req.length, is_encrypted, is_last); if (res) tx_state.state = TX_STATE_RW_COMMAND; send_response: pss->u.resp.tpm_result = res; fuse_reply_ioctl(req, 0, pss, sizeof(*pss)); } /* * ptm_get_stateblob_part: get part of a state blob * * @blobtype: the type of blob to get * @buffer: the buffer this function will write the blob into * @buffer_size: the size of the buffer * @offset: the offset into the state blob * @copied: pointer to int to indicate the number of bytes that were copied * @is_encryped: returns whether the state blob is encrypted */ static TPM_RESULT ptm_get_stateblob_part(uint32_t blobtype, unsigned char *buffer, size_t buffer_size, uint32_t offset, uint32_t *copied, TPM_BOOL decrypt, TPM_BOOL *is_encrypted) { TPM_RESULT res = 0; if (!cached_stateblob_is_loaded(blobtype, decrypt)) { res = cached_stateblob_load(blobtype, decrypt); } if (res == 0) { cached_stateblob_copy(buffer, buffer_size, offset, copied, is_encrypted); } return res; } /* * ptm_get_stateblob: Get the state blob from the TPM using ioctl() */ static void ptm_get_stateblob(fuse_req_t req, ptm_getstate *pgs) { TPM_RESULT res = 0; uint32_t blobtype = pgs->u.req.type; TPM_BOOL decrypt = ((pgs->u.req.state_flags & PTM_STATE_FLAG_DECRYPTED) != 0); TPM_BOOL is_encrypted = FALSE; uint32_t copied = 0; uint32_t offset = pgs->u.req.offset; uint32_t totlength; res = ptm_get_stateblob_part(blobtype, pgs->u.resp.data, sizeof(pgs->u.resp.data), pgs->u.req.offset, &copied, decrypt, &is_encrypted); totlength = cached_stateblob_get_bloblength(); pgs->u.resp.state_flags = 0; if (is_encrypted) pgs->u.resp.state_flags |= PTM_STATE_FLAG_ENCRYPTED; pgs->u.resp.length = copied; pgs->u.resp.totlength = totlength; pgs->u.resp.tpm_result = res; logprintf(STDERR_FILENO, "Serialized state type %d, length=%d, totlength=%d, res=%d\n", blobtype, copied, totlength, res); if (res == 0) { if (offset + copied < totlength) { /* last byte was not copied */ tx_state.state = TX_STATE_GET_STATE_BLOB; tx_state.blobtype = pgs->u.req.type; tx_state.blob_is_encrypted = is_encrypted; tx_state.offset = copied; } else { /* last byte was copied */ tx_state.state = TX_STATE_RW_COMMAND; } } else { /* error occurred */ tx_state.state = TX_STATE_RW_COMMAND; } fuse_reply_ioctl(req, 0, pgs, sizeof(pgs->u.resp)); } /*********************************** write() support *************************/ /* * ptm_write_stateblob: Write the state blob using the write() interface * * @req: the fuse_req_t * @buf: the buffer with the data * @size: the number of bytes in the buffer * * The data are appended to an existing buffer that was created with the * initial ioctl(). */ static void ptm_write_stateblob(fuse_req_t req, const char *buf, size_t size) { TPM_RESULT res; res = ptm_set_stateblob_append(tx_state.blobtype, (unsigned char *)buf, size, tx_state.blob_is_encrypted, (size == 0)); if (res) { tx_state.state = TX_STATE_RW_COMMAND; fuse_reply_err(req, EIO); } else { fuse_reply_write(req, size); } } /* * ptm_write_cmd: User writing a TPM command * * req: fuse_req_t * buf: the buffer containing the TPM command * size: the size of the buffer * tpmversion: the version of the TPM */ static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size, TPMLIB_TPMVersion l_tpmversion) { ptm_req_len = size; ptm_res_len = 0; /* prevent other threads from writing or doing ioctls */ g_mutex_lock(FILE_OPS_LOCK); if (tpm_running) { /* ensure that we only ever work on one TPM command */ if (worker_thread_is_busy()) { fuse_reply_err(req, EBUSY); goto cleanup; } if (ptm_req_len > TPM_REQ_MAX) ptm_req_len = TPM_REQ_MAX; /* process SetLocality command, if */ tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot, (unsigned char *)buf, ptm_req_len, locality_flags, &locality, tpmversion); if (ptm_res_len) { ptm_read_offset = 0; goto skip_process; } if (tpmlib_is_request_cancelable(l_tpmversion, (const unsigned char*)buf, ptm_req_len)) { /* have command processed by thread pool */ memcpy(ptm_request, buf, ptm_req_len); msg.type = MESSAGE_TPM_CMD; worker_thread_mark_busy(); g_thread_pool_push(pool, &msg, NULL); } else { /* direct processing */ TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot, (unsigned char *)buf, ptm_req_len); ptm_read_offset = 0; } } else { /* TPM not initialized; return error */ ptm_write_fatal_error_response(l_tpmversion); } skip_process: fuse_reply_write(req, ptm_req_len); cleanup: g_mutex_unlock(FILE_OPS_LOCK); return; } /* * ptm_write: low-level write() interface; calls approriate function depending * on what is being transferred using the write() */ static void ptm_write(fuse_req_t req, const char *buf, size_t size, off_t off, struct fuse_file_info *fi) { switch (tx_state.state) { case TX_STATE_RW_COMMAND: ptm_write_cmd(req, buf, size, tpmversion); break; case TX_STATE_GET_STATE_BLOB: fuse_reply_err(req, EIO); tx_state.state = TX_STATE_RW_COMMAND; break; case TX_STATE_SET_STATE_BLOB: ptm_write_stateblob(req, buf, size); break; } } /* * ptm_open: interface to POSIX open() */ static void ptm_open(fuse_req_t req, struct fuse_file_info *fi) { tx_state.state = TX_STATE_RW_COMMAND; fuse_reply_open(req, fi); } /* * ptm_ioctl : ioctl execution * * req: the fuse_req_t used to send response with * cmd: the ioctl request code * arg: the pointer the application used for calling the ioctl (3rd param) * fi: * flags: some flags provided by fuse * in_buf: the copy of the input buffer * in_bufsz: size of the input buffer; provided by fuse and has size of * needed buffer * out_bufsz: size of the output buffer; provided by fuse and has size of * needed buffer */ static void ptm_ioctl(fuse_req_t req, int cmd, void *arg, struct fuse_file_info *fi, unsigned flags, const void *in_buf, size_t in_bufsz, size_t out_bufsz) { TPM_RESULT res = TPM_FAIL; bool exit_prg = FALSE; ptm_init *init_p; TPM_MODIFIER_INDICATOR orig_locality; /* some commands have to wait until the worker thread is done */ switch(cmd) { case PTM_GET_CAPABILITY: case PTM_SET_LOCALITY: case PTM_CANCEL_TPM_CMD: case PTM_GET_CONFIG: case PTM_SET_BUFFERSIZE: /* no need to wait */ break; case PTM_INIT: case PTM_SHUTDOWN: case PTM_GET_TPMESTABLISHED: case PTM_RESET_TPMESTABLISHED: case PTM_HASH_START: case PTM_HASH_DATA: case PTM_HASH_END: case PTM_STORE_VOLATILE: case PTM_GET_STATEBLOB: case PTM_SET_STATEBLOB: if (tpm_running) worker_thread_wait_done(); break; } /* prevent other threads from writing or doing ioctls */ g_mutex_lock(FILE_OPS_LOCK); switch (cmd) { case PTM_GET_CAPABILITY: if (out_bufsz != sizeof(ptm_cap)) { struct iovec iov = { arg, sizeof(uint8_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_cap ptm_caps; switch (tpmversion) { case TPMLIB_TPM_VERSION_2: ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | PTM_CAP_SET_LOCALITY | PTM_CAP_HASHING | PTM_CAP_CANCEL_TPM_CMD | PTM_CAP_STORE_VOLATILE | PTM_CAP_RESET_TPMESTABLISHED | PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | PTM_CAP_STOP | PTM_CAP_GET_CONFIG | PTM_CAP_SET_BUFFERSIZE | PTM_CAP_GET_INFO; break; case TPMLIB_TPM_VERSION_1_2: ptm_caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | PTM_CAP_SET_LOCALITY | PTM_CAP_HASHING | PTM_CAP_CANCEL_TPM_CMD | PTM_CAP_STORE_VOLATILE | PTM_CAP_RESET_TPMESTABLISHED | PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | PTM_CAP_STOP | PTM_CAP_GET_CONFIG | PTM_CAP_SET_BUFFERSIZE | PTM_CAP_GET_INFO; break; } fuse_reply_ioctl(req, 0, &ptm_caps, sizeof(ptm_caps)); } break; case PTM_INIT: if (in_bufsz != sizeof(ptm_init)) { struct iovec iov = { arg, sizeof(uint8_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { init_p = (ptm_init *)in_buf; worker_thread_end(); TPMLIB_Terminate(); tpm_running = false; if (tpm_start(init_p->u.req.init_flags, tpmversion, &res) < 0) { logprintf(STDERR_FILENO, "Error: Could not initialize the TPM.\n"); } else { tpm_running = true; } init_p->u.resp.tpm_result = res; fuse_reply_ioctl(req, 0, init_p, sizeof(*init_p)); } break; case PTM_STOP: worker_thread_end(); res = TPM_SUCCESS; TPMLIB_Terminate(); tpm_running = false; free(ptm_response); ptm_response = NULL; fuse_reply_ioctl(req, 0, &res, sizeof(res)); break; case PTM_SHUTDOWN: worker_thread_end(); res = TPM_SUCCESS; TPMLIB_Terminate(); free(ptm_response); ptm_response = NULL; fuse_reply_ioctl(req, 0, &res, sizeof(res)); exit_prg = TRUE; break; case PTM_GET_TPMESTABLISHED: if (!tpm_running) goto error_not_running; if (out_bufsz != sizeof(ptm_est)) { struct iovec iov = { arg, sizeof(uint8_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_est te; memset(&te, 0, sizeof(te)); te.u.resp.tpm_result = TPM_IO_TpmEstablished_Get(&te.u.resp.bit); fuse_reply_ioctl(req, 0, &te, sizeof(te)); } break; case PTM_RESET_TPMESTABLISHED: if (!tpm_running) goto error_not_running; if (in_bufsz != sizeof(ptm_reset_est)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_reset_est *re = (ptm_reset_est *)in_buf; if (re->u.req.loc > 4) { res = TPM_BAD_LOCALITY; } else { /* set locality and reset flag in one command */ orig_locality = locality; locality = re->u.req.loc; res = TPM_IO_TpmEstablished_Reset(); locality = orig_locality; fuse_reply_ioctl(req, 0, &res, sizeof(res)); } } break; case PTM_SET_LOCALITY: if (in_bufsz != sizeof(ptm_loc)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_loc *l = (ptm_loc *)in_buf; if (l->u.req.loc > 4 || (l->u.req.loc == 4 && locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) { res = TPM_BAD_LOCALITY; } else { res = TPM_SUCCESS; locality = l->u.req.loc; } l->u.resp.tpm_result = res; fuse_reply_ioctl(req, 0, l, sizeof(*l)); } break; case PTM_HASH_START: if (!tpm_running) goto error_not_running; res = TPM_IO_Hash_Start(); fuse_reply_ioctl(req, 0, &res, sizeof(res)); break; case PTM_HASH_DATA: if (!tpm_running) goto error_not_running; if (in_bufsz != sizeof(ptm_hdata)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_hdata *data = (ptm_hdata *)in_buf; if (data->u.req.length <= sizeof(data->u.req.data)) { res = TPM_IO_Hash_Data(data->u.req.data, data->u.req.length); } else { res = TPM_FAIL; } data->u.resp.tpm_result = res; fuse_reply_ioctl(req, 0, data, sizeof(*data)); } break; case PTM_HASH_END: if (!tpm_running) goto error_not_running; res = TPM_IO_Hash_End(); fuse_reply_ioctl(req, 0, &res, sizeof(res)); break; case PTM_CANCEL_TPM_CMD: if (!tpm_running) goto error_not_running; /* for cancellation to work, the TPM would have to * execute in another thread that polls on a cancel * flag */ res = TPMLIB_CancelCommand(); fuse_reply_ioctl(req, 0, &res, sizeof(res)); break; case PTM_STORE_VOLATILE: if (!tpm_running) goto error_not_running; res = SWTPM_NVRAM_Store_Volatile(); fuse_reply_ioctl(req, 0, &res, sizeof(res)); cached_stateblob_free(); break; case PTM_GET_STATEBLOB: if (!tpm_running) goto error_not_running; if (in_bufsz != sizeof(ptm_getstate)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_get_stateblob(req, (ptm_getstate *)in_buf); } break; case PTM_SET_STATEBLOB: if (tpm_running) goto error_running; /* tpm state dir must be set */ SWTPM_NVRAM_Init(); if (in_bufsz != sizeof(ptm_setstate)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_set_stateblob(req, (ptm_setstate *)in_buf); } break; case PTM_GET_CONFIG: if (out_bufsz != sizeof(ptm_getconfig)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_getconfig pgs; pgs.u.resp.tpm_result = 0; pgs.u.resp.flags = 0; if (SWTPM_NVRAM_Has_FileKey()) pgs.u.resp.flags |= PTM_CONFIG_FLAG_FILE_KEY; if (SWTPM_NVRAM_Has_MigrationKey()) pgs.u.resp.flags |= PTM_CONFIG_FLAG_MIGRATION_KEY; fuse_reply_ioctl(req, 0, &pgs, sizeof(pgs)); } break; case PTM_SET_BUFFERSIZE: if (out_bufsz != sizeof(ptm_setbuffersize)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_setbuffersize *in_psbs = (ptm_setbuffersize *)in_buf; ptm_setbuffersize out_psbs; uint32_t buffersize, minsize, maxsize; buffersize = in_psbs->u.req.buffersize; if (buffersize > 0 && tpm_running) goto error_running; buffersize = TPMLIB_SetBufferSize(buffersize, &minsize, &maxsize); out_psbs.u.resp.tpm_result = TPM_SUCCESS; out_psbs.u.resp.buffersize = buffersize; out_psbs.u.resp.minsize = minsize; out_psbs.u.resp.maxsize = maxsize; fuse_reply_ioctl(req, 0, &out_psbs, sizeof(out_psbs)); } break; case PTM_GET_INFO: if (out_bufsz != sizeof(ptm_getinfo)) { struct iovec iov = { arg, sizeof(uint32_t) }; fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0); } else { ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf; ptm_getinfo out_pgi; char *info_data; uint32_t length, offset; info_data = TPMLIB_GetInfo(in_pgi->u.req.flags); if (!info_data) goto error_memory; offset = in_pgi->u.req.offset; if (offset >= strlen(info_data)) { free(info_data); goto error_bad_input; } length = min(strlen(info_data) + 1 - offset, sizeof(out_pgi.u.resp.buffer)); out_pgi.u.resp.tpm_result = 0; out_pgi.u.resp.totlength = strlen(info_data) + 1; out_pgi.u.resp.length = length; /* client has to collect whole string in case buffer is too small */ memcpy(out_pgi.u.resp.buffer, &info_data[offset], length); free(info_data); fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi)); } break; default: fuse_reply_err(req, EINVAL); } cleanup: g_mutex_unlock(FILE_OPS_LOCK); if (exit_prg) { logprintf(STDOUT_FILENO, "CUSE TPM is shutting down.\n"); ptm_cleanup(); fuse_session_exit(ptm_fuse_session); } return; error_bad_input: res = TPM_BAD_PARAMETER; fuse_reply_ioctl(req, 0, &res, sizeof(res)); goto cleanup; error_running: error_not_running: res = TPM_BAD_ORDINAL; fuse_reply_ioctl(req, 0, &res, sizeof(res)); goto cleanup; error_memory: res = TPM_SIZE; fuse_reply_ioctl(req, 0, &res, sizeof(res)); goto cleanup; } static void ptm_init_done(void *userdata) { struct cuse_param *param = userdata; int ret; /* at this point the entry in /dev/ is available */ if (pidfile_write(getpid()) < 0) { ret = -13; goto error_exit; } if (param->runas) { ret = change_process_owner(param->runas); if (ret) goto error_exit; } if (create_seccomp_profile(true, param->seccomp_action) < 0) { ret = -14; goto error_exit; } return; error_exit: ptm_cleanup(); exit(ret); } static void ptm_cleanup(void) { pidfile_remove(); log_global_free(); tpmstate_global_free(); SWTPM_NVRAM_Shutdown(); } static const struct cuse_lowlevel_ops clops = { .open = ptm_open, .read = ptm_read, .write = ptm_write, .ioctl = ptm_ioctl, .init_done = ptm_init_done, }; /* ptm_cuse_lowlevel_main is like cuse_lowlevel_main with the difference that * it uses a global ptm_fuse_session so we can call fuse_session_exit() on it * for a graceful exit with cleanups. */ static int ptm_cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci, const struct cuse_lowlevel_ops *clop, void *userdata) { int mt; int ret; struct cuse_param *param = userdata; ptm_fuse_session = cuse_lowlevel_setup(argc, argv, ci, clop, &mt, userdata); if (ptm_fuse_session == NULL) return 1; if (param->seccomp_action == SWTPM_SECCOMP_ACTION_NONE && mt) ret = fuse_session_loop_mt(ptm_fuse_session); else ret = fuse_session_loop(ptm_fuse_session); cuse_lowlevel_teardown(ptm_fuse_session); if (ret < 0) ret = 1; return ret; } #ifndef HAVE_SWTPM_CUSE_MAIN int main(int argc, char **argv) { const char *prgname = argv[0]; const char *iface = ""; #else int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface) { #endif int opt, longindex = 0; static struct option longopts[] = { {"maj" , required_argument, 0, 'M'}, {"min" , required_argument, 0, 'm'}, {"name" , required_argument, 0, 'n'}, {"runas" , required_argument, 0, 'r'}, {"log" , required_argument, 0, 'l'}, {"locality" , required_argument, 0, 'L'}, {"key" , required_argument, 0, 'k'}, {"migration-key" , required_argument, 0, 'K'}, {"pid" , required_argument, 0, 'p'}, {"tpmstate" , required_argument, 0, 's'}, {"flags" , required_argument, 0, 'F'}, {"tpm2" , no_argument, 0, '2'}, {"help" , no_argument, 0, 'h'}, {"version" , no_argument, 0, 'v'}, #ifdef WITH_SECCOMP {"seccomp" , required_argument, 0, 'S'}, #endif {"print-capabilities" , no_argument, 0, 'a'}, {NULL , 0 , 0, 0 }, }; struct cuse_info cinfo; struct cuse_param param = { .startupType = _TPM_ST_NONE, }; const char *devname = NULL; char *cinfo_argv[1] = { 0 }; unsigned int num; struct passwd *passwd; const char *tpmdir; int n, tpmfd; char path[PATH_MAX]; int ret = 0; bool printcapabilities = false; bool need_init_cmd = true; TPM_RESULT res; memset(&cinfo, 0, sizeof(cinfo)); memset(¶m, 0, sizeof(param)); log_set_prefix("swtpm: "); tpmversion = TPMLIB_TPM_VERSION_1_2; while (true) { opt = getopt_long(argc, argv, "M:m:n:r:hv", longopts, &longindex); if (opt == -1) break; switch (opt) { case 'M': /* major */ if (sscanf(optarg, "%u", &num) != 1) { logprintf(STDERR_FILENO, "Could not parse major number\n"); ret = -1; goto exit; } if (num > 65535) { logprintf(STDERR_FILENO, "Major number outside valid range [0 - 65535]\n"); ret = -1; goto exit; } cinfo.dev_major = num; break; case 'm': /* minor */ if (sscanf(optarg, "%u", &num) != 1) { logprintf(STDERR_FILENO, "Could not parse major number\n"); ret = -1; goto exit; } if (num > 65535) { logprintf(STDERR_FILENO, "Major number outside valid range [0 - 65535]\n"); ret = -1; goto exit; } cinfo.dev_minor = num; break; case 'n': /* name */ if (!cinfo.dev_info_argc) { cinfo_argv[0] = calloc(1, strlen("DEVNAME=") + strlen(optarg) + 1); if (!cinfo_argv[0]) { logprintf(STDERR_FILENO, "Out of memory\n"); ret = -1; goto exit; } devname = optarg; strcpy(cinfo_argv[0], "DEVNAME="); strcat(cinfo_argv[0], optarg); cinfo.dev_info_argc = 1; cinfo.dev_info_argv = (const char **)cinfo_argv; } break; case 'r': /* runas */ param.runas = optarg; break; case 'l': /* log */ param.logging = optarg; break; case 'k': /* key */ param.keydata = optarg; break; case 'K': /* migration-key */ param.migkeydata = optarg; break; case 'p': /* pid */ param.piddata = optarg; break; case 's': /* tpmstate */ param.tpmstatedata = optarg; break; case 'L': param.localitydata = optarg; break; case 'F': param.flagsdata = optarg; break; case '2': tpmversion = TPMLIB_TPM_VERSION_2; break; case 'S': param.seccompdata = optarg; break; case 'h': /* help */ fprintf(stdout, usage, prgname, iface); goto exit; case 'a': printcapabilities = true; break; case 'v': /* version */ fprintf(stdout, "TPM emulator CUSE interface version %d.%d.%d, " "Copyright (c) 2014-2015 IBM Corp.\n", SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); goto exit; } } if (optind < argc) { logprintf(STDERR_FILENO, "Unknown parameter '%s'\n", argv[optind]); ret = EXIT_FAILURE; goto exit; } /* * choose the TPM version early so that getting/setting * buffer size works. */ if (TPMLIB_ChooseTPMVersion(tpmversion) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not choose TPM version.\n"); ret = EXIT_FAILURE; goto exit; } if (printcapabilities) { ret = capabilities_print_json(true) ? EXIT_FAILURE : EXIT_SUCCESS; goto exit; } SWTPM_NVRAM_Set_TPMVersion(tpmversion); if (!cinfo.dev_info_argv) { logprintf(STDERR_FILENO, "Error: device name missing\n"); ret = -2; goto exit; } if (handle_log_options(param.logging) < 0 || handle_key_options(param.keydata) < 0 || handle_migration_key_options(param.migkeydata) < 0 || handle_pid_options(param.piddata) < 0 || handle_tpmstate_options(param.tpmstatedata) < 0 || handle_seccomp_options(param.seccompdata, ¶m.seccomp_action) < 0 || handle_locality_options(param.localitydata, &locality_flags) < 0 || handle_flags_options(param.flagsdata, &need_init_cmd, ¶m.startupType) < 0) { ret = -3; goto exit; } if (setuid(0)) { logprintf(STDERR_FILENO, "Error: Unable to setuid root. uid = %d, " "euid = %d, gid = %d\n", getuid(), geteuid(), getgid()); ret = -4; goto exit; } if (param.runas) { if (!(passwd = getpwnam(param.runas))) { logprintf(STDERR_FILENO, "User '%s' does not exist\n", param.runas); ret = -5; goto exit; } } tpmdir = tpmstate_get_dir(); if (tpmdir == NULL) { logprintf(STDERR_FILENO, "Error: No TPM state directory is defined; " "TPM_PATH is not set\n"); ret = -1; goto exit; } n = snprintf(path, sizeof(path), "/dev/%s", devname); if (n < 0) { logprintf(STDERR_FILENO, "Error: Could not create device file name\n"); ret = -1; goto exit; } if (n >= (int)sizeof(path)) { logprintf(STDERR_FILENO, "Error: Buffer too small to create device file name\n"); ret = -1; goto exit; } tpmfd = open(path, O_RDWR); if (tpmfd >= 0) { close(tpmfd); logprintf(STDERR_FILENO, "Error: A device '%s' already exists.\n", path); ret = -1; goto exit; } if (tpmlib_register_callbacks(&cbs) != TPM_SUCCESS) { ret = -1; goto exit; } worker_thread_init(); if (!need_init_cmd) { if (tpm_start(0, tpmversion, &res) < 0) { ret = -1; goto exit; } tpm_running = true; } if (param.startupType != _TPM_ST_NONE) { if (ptm_send_startup(param.startupType, tpmversion) < 0) { ret = -1; goto exit; } } #if GLIB_MINOR_VERSION >= 32 g_mutex_init(FILE_OPS_LOCK); #else FILE_OPS_LOCK = g_mutex_new(); #endif ret = ptm_cuse_lowlevel_main(1, argv, &cinfo, &clops, ¶m); exit: ptm_cleanup(); free(cinfo_argv[0]); return ret; } swtpm-0.6.3/src/swtpm/key.c000066400000000000000000000272561421141172300155770ustar00rootroot00000000000000/* * key.c -- Common key handling code for swtpm and swtpm_cuse * * (c) Copyright IBM Corporation 2014, 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "key.h" #include "logging.h" #include "utils.h" /* * key_format_from_string: * Convert the string into a key format identifier * @format: either 'hex' or 'binary' * * Returns a key format identifier */ enum key_format key_format_from_string(const char *format) { if (!strcmp(format, "hex")) { return KEY_FORMAT_HEX; } else if (!strcmp(format, "binary")) { return KEY_FORMAT_BINARY; } logprintf(STDERR_FILENO, "Unknown key format '%s'.\n", format); return KEY_FORMAT_UNKNOWN; } /* * encryption_mode_from_string: * Convert the string into a encryption mode identifier * @mode: string describing encryption mode * @keylen: the length of the key in bytes * * Returns an encryption mode identifier */ enum encryption_mode encryption_mode_from_string(const char *mode, size_t *keylen) { if (!strcmp(mode, "aes-cbc") || !strcmp(mode, "aes-128-cbc")) { *keylen = 128/8; return ENCRYPTION_MODE_AES_CBC; } else if (!strcmp(mode, "aes-256-cbc")) { *keylen = 256/8; return ENCRYPTION_MODE_AES_CBC; } return ENCRYPTION_MODE_UNKNOWN; } /* * kdf_identifier_from_string: * Convert the string in a kdf identifier * @mode: string describing the kdf * * Return a kdf identifier */ enum kdf_identifier kdf_identifier_from_string(const char *kdf) { if (!strcmp(kdf, "sha512")) { return KDF_IDENTIFIER_SHA512; } else if (!strcmp(kdf, "pbkdf2")) { return KDF_IDENTIFIER_PBKDF2; } return KDF_IDENTIFIER_UNKNOWN; } /* * key_stream_to_bin * Convert a stream of ASCII hex digits into a key; convert a maximum of * bin_size bytes; * * @input: input data holding hex digits * @bin: output field of bin_size * @bin_size: max. number of bytes to convert * * Returns the number of digits that were converted. */ static ssize_t key_stream_to_bin(const char *input, unsigned char *bin, size_t bin_size) { ssize_t digits = 0; int n, num; while (input[digits] && !isspace((int)input[digits]) && bin_size > (size_t)digits / 2) { num = sscanf(&input[digits], "%2hhx%n", &bin[digits/2], &n); if (num != 1 || n != 2) return -1; digits += 2; } if (input[digits] && !isspace((int)input[digits])) return -1; return (digits != 0) ? digits : -1; } /* * key_parse_as_hexkey: * Parse the raw key data as a key in ASCII hex format; they key may * have a leading '0x'. * @rawkey: ASCII data for a hex key with possible leading '0x' * @key: buffer for key * @keylen: actual key len returned by this function * @maxkeylen: the max. size of the key; this is equivalent to the size of * the key buffer * Returns 0 on success, -1 on failure */ static int key_parse_as_hexkey(const char *rawkey, unsigned char *key, size_t *keylen, size_t maxkeylen) { ssize_t digits; off_t offset = 0; if (!strncmp(rawkey, "0x", 2)) offset = 2; digits = key_stream_to_bin(&rawkey[offset], key, maxkeylen); if (digits < 0) { logprintf(STDERR_FILENO, "Could not parse key hex string into %zu byte buffer.\n", maxkeylen); return -1; } else if (digits == 128/4) { *keylen = 128/8; } else if (digits == 256/4) { *keylen = 256/8; } else { logprintf(STDERR_FILENO, "Unsupported key length with %zu digits.\n", digits); return -1; } if (*keylen < maxkeylen) { logprintf(STDERR_FILENO, "The provided key is too short. Got %zu bytes, need %zu.\n", *keylen, maxkeylen); return -1; } return 0; } /* * key_load_key_fd: * Load the raw key data from a file and convert it to a key. * @fd: file descriptor to read raw key data from * @keyformat: the format the raw key data are in; may either indicate * binary data or hex string * @key: the buffer for holding the converted key * @keylen: the actual key len of the converted key returned by this * function * @maxkeylen: the max. size of the key; corresponds to the size of the * key buffer */ int key_load_key_fd(int fd, enum key_format keyformat, unsigned char *key, size_t *keylen, size_t maxkeylen) { int ret = -1; char filebuffer[2 + 256/4 + 1 + 1]; ssize_t len; len = read_eintr(fd, filebuffer, sizeof(filebuffer) - 1); if (len < 0) { logprintf(STDERR_FILENO, "Unable to read key: %s\n", strerror(errno)); return -1; } filebuffer[len] = 0; switch (keyformat) { case KEY_FORMAT_BINARY: *keylen = len; if (maxkeylen < (size_t)len) { logprintf(STDERR_FILENO, "Key is larger than buffer (%zu > %zu).\n", len, maxkeylen); return -1; } memcpy(key, filebuffer, len); ret = 0; break; case KEY_FORMAT_HEX: if (key_parse_as_hexkey(filebuffer, key, keylen, maxkeylen) < 0) return -1; ret = 0; break; case KEY_FORMAT_UNKNOWN: break; } return ret; } /* * key_load_key: * Load the raw key data from a file and convert it to a key. * @filename: file holding the raw key data * @keyformat: the format the raw key data are in; may either indicate * binary data or hex string * @key: the buffer for holding the converted key * @keylen: the actual key len of the converted key returned by this * function * @maxkeylen: the max. size of the key; corresponds to the size of the * key buffer */ int key_load_key(const char *filename, enum key_format keyformat, unsigned char *key, size_t *keylen, size_t maxkeylen) { int ret; int fd; fd = open(filename, O_RDONLY); if (fd < 0) { logprintf(STDERR_FILENO, "Unable to open file %s: %s\n", filename, strerror(errno)); return -1; } ret = key_load_key_fd(fd, keyformat, key, keylen, maxkeylen); close(fd); return ret; } /* * key_from_pwdfile: * Read the password from the given file descriptor, convert the password into * a key by applying a KDF on the password and use the first bytes * of the hash as the key. * @fd: file descriptor to read password from * @key: the buffer for holding the key * @keylen: the actual key len of the converted key returned by this * function * @maxkeylen: the max. size of the key; corresponds to the size of the * key buffer * @kdfid: the kdf to invoke to create the key */ int key_from_pwdfile_fd(int fd, unsigned char *key, size_t *keylen, size_t maxkeylen, enum kdf_identifier kdfid) { unsigned char *filebuffer = NULL; size_t filelen = 1024; off_t offset = 0; ssize_t len; unsigned char hashbuf[SHA512_DIGEST_LENGTH]; int ret = -1; const unsigned char salt[] = {'s','w','t','p','m'}; if (maxkeylen > sizeof(hashbuf)) { logprintf(STDERR_FILENO, "Request keylength is too big (%zu > %zu)\n", maxkeylen, sizeof(hashbuf)); return -1; } while (true) { unsigned char *tmp = filebuffer; filebuffer = realloc(tmp, filelen); if (!filebuffer) { logprintf(STDERR_FILENO, "Could not allocate %zu bytes for filebuffer\n", filelen); free(tmp); goto exit; } len = read_eintr(fd, &filebuffer[offset], filelen - offset); if (len < 0) { logprintf(STDERR_FILENO, "Unable to read passphrase: %s\n", strerror(errno)); goto exit; } /* EOF ? */ if ((size_t)len < filelen - offset) { len += offset; break; } /* expecting more bytes */ offset += len; filelen += 1024; } *keylen = maxkeylen; switch (kdfid) { case KDF_IDENTIFIER_SHA512: if (sizeof(hashbuf) < *keylen) { logprintf(STDERR_FILENO, "Requested %zu bytes for key, only got %zu.\n", *keylen, sizeof(hashbuf)); goto exit; } SHA512(filebuffer, len, hashbuf); memcpy(key, hashbuf, *keylen); break; case KDF_IDENTIFIER_PBKDF2: if (PKCS5_PBKDF2_HMAC((const char *)filebuffer, len, salt, sizeof(salt), 1000, EVP_sha512(), *keylen, key) != 1) { logprintf(STDERR_FILENO, "PKCS5_PBKDF2_HMAC with SHA512 failed\n"); goto exit; } break; case KDF_IDENTIFIER_UNKNOWN: logprintf(STDERR_FILENO, "Unknown KDF\n"); goto exit; } ret = 0; exit: free(filebuffer); return ret; } /* * key_from_pwdfile: * Read the password from the given file, convert the password into * a key by applying a KDF on the password and use the first bytes * of the hash as the key. * @filename: name of the file holding the password * @key: the buffer for holding the key * @keylen: the actual key len of the converted key returned by this * function * @maxkeylen: the max. size of the key; corresponds to the size of the * key buffer * @kdfid: the kdf to invoke to create the key */ int key_from_pwdfile(const char *filename, unsigned char *key, size_t *keylen, size_t maxkeylen, enum kdf_identifier kdfid) { int ret; int fd; fd = open(filename, O_RDONLY); if (fd < 0) { logprintf(STDERR_FILENO, "Unable to open file %s : %s\n", filename, strerror(errno)); return -1; } ret = key_from_pwdfile_fd(fd, key, keylen, maxkeylen, kdfid); close(fd); return ret; } swtpm-0.6.3/src/swtpm/key.h000066400000000000000000000055241421141172300155760ustar00rootroot00000000000000/* * key.h -- Header file for key handling functions for swtpm and swtpm_cuse * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_KEY_H #define _SWTPM_KEY_H enum key_format { KEY_FORMAT_UNKNOWN = 0, KEY_FORMAT_BINARY = 1, KEY_FORMAT_HEX = 2, }; enum encryption_mode { ENCRYPTION_MODE_UNKNOWN = 0, ENCRYPTION_MODE_AES_CBC = 1, }; enum kdf_identifier { KDF_IDENTIFIER_UNKNOWN = 0, KDF_IDENTIFIER_SHA512 = 1, KDF_IDENTIFIER_PBKDF2 = 2, }; enum key_format key_format_from_string(const char *format); enum encryption_mode encryption_mode_from_string(const char *mode, size_t *keylen); enum kdf_identifier kdf_identifier_from_string(const char *kdf); int key_load_key(const char *filename, enum key_format keyformat, unsigned char *key, size_t *keylen, size_t maxkeylen); int key_load_key_fd(int fd, enum key_format keyformat, unsigned char *key, size_t *keylen, size_t maxkeylen); int key_from_pwdfile(const char *pwdfile, unsigned char *key, size_t *keylen, size_t maxkeylen, enum kdf_identifier kdfid); int key_from_pwdfile_fd(int pwdfile_fd, unsigned char *key, size_t *keylen, size_t maxkeylen, enum kdf_identifier kdfid); #endif /* _SWTPM_KEY_H */ swtpm-0.6.3/src/swtpm/locality.h000066400000000000000000000034711421141172300166250ustar00rootroot00000000000000/* * locality.h -- locality parameters * * (c) Copyright IBM Corporation 2017. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_LOCALITY_H_ #define _SWTPM_LOCALITY_H_ #define LOCALITY_FLAG_REJECT_LOCALITY_4 (1 << 0) #define LOCALITY_FLAG_ALLOW_SETLOCALITY (1 << 1) #endif /* _SWTPM_LOCALITY_H_ */ swtpm-0.6.3/src/swtpm/logging.c000066400000000000000000000167051421141172300164320ustar00rootroot00000000000000/* * logging.c -- Logging functions * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "sys_dependencies.h" #include #include #include #include #include #include #include #include #include #include #include "logging.h" #include "utils.h" #include #define CONSOLE_LOGGING 2 /* stderr */ #define SUPPRESS_LOGGING -1 static int logfd = CONSOLE_LOGGING; static unsigned int log_level = 1; static char *log_prefix; static void log_prefix_clear(void) { free(log_prefix); log_prefix = NULL; } /* * log_init: * Initialize the logging to log into a file with the given name. * @filename: the log filename; use '-' to suppress logging * * Returns 0 on success, -1 on failure with errno set. */ int log_init(const char *filename, bool truncate) { int flags; if (!strcmp(filename, "-")) { logfd = SUPPRESS_LOGGING; return 0; } if (!truncate) { flags = O_WRONLY|O_CREAT|O_APPEND|O_NOFOLLOW; } else { flags = O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW; } logfd = open(filename, flags, S_IRUSR|S_IWUSR); if (logfd < 0) return -1; log_prefix_clear(); return 0; } /* * log_init_fd: * Initialize the logging and have the logs written to the given file * descriptor. * @fd: file descriptor to log to * * Returns 0 on success, -1 on failure with errno set. */ int log_init_fd(int fd) { int flags; close(logfd); logfd = fd; if (logfd >= 0) { flags = fcntl(logfd, F_GETFL); if (flags == -1) return -1; if ((flags & (O_RDWR|O_WRONLY)) == 0) { errno = EPERM; return -1; } } log_prefix_clear(); return 0; } /* * log_set_level * Set the log level; the higher the level, the more is printed * @level: the log level */ int log_set_level(unsigned int level) { log_level = level; char *prefixbuf = NULL; int ret = 0; if (level >= 5) { TPMLIB_SetDebugLevel(level - 4); if (asprintf(&prefixbuf, "%s%s", log_prefix ? log_prefix : "", " ") < 0) { ret = -1; goto err_exit; } TPMLIB_SetDebugPrefix(prefixbuf); free(prefixbuf); } if (logfd != SUPPRESS_LOGGING) TPMLIB_SetDebugFD(logfd); err_exit: return ret; } /* * log_set_prefix * Set the logging prefix; this function should be * call before log_set_level. * * @prefix: string to print before every line */ int log_set_prefix(const char *prefix) { free(log_prefix); if (prefix) { log_prefix = strdup(prefix); if (!log_prefix) return -1; } else { log_prefix = NULL; } return 0; } /* * Check whether to write the string to the log following * the log level * @string: the string to print * * Returns -1 in case the string must not be printed following * the log level, the number of bytes used for indentation otherwise. */ int log_check_string(const char *string) { unsigned int level, i; if (log_level == 0) return -1; level = log_level - 1; i = 0; while (1) { if (string[i] == 0) return -1; if (string[i] != ' ') return i; if (i == level) return -1; i++; } } /* * log_global_free: free memory allocated for global variables */ void log_global_free(void) { free(log_prefix); log_prefix = NULL; TPMLIB_SetDebugPrefix(NULL); } /* * _logprintf: * Format a log line and output it to the given file descriptor. * @fd: file descriptor to log to * @format: printf type of format for the string * @ap: list of var args to format * @check_indent: whether to check the level or force printing * * Returns the number of bytes written on success, a value < 0 on error. */ static int _logprintf(int fd, const char *format, va_list ap, bool check_indent) { char *buf = NULL; int ret = 0, len = 0; if (logfd == SUPPRESS_LOGGING) return 0; if (logfd > 0) fd = logfd; ret = vasprintf(&buf, format, ap); if (ret < 0) goto cleanup; if (!check_indent || log_check_string(buf) >= 0) { if (log_prefix) { ret = write_full(fd, log_prefix, strlen(log_prefix)); if (ret < 0) goto err_exit; len = ret; } ret = write_full(fd, buf, strlen(buf)); if (ret < 0) goto err_exit; ret += len; } else ret = 0; err_exit: free(buf); cleanup: return ret; } /* * logprintf: * log to stderr or logfile * @fd : the foile descriptor to log to * @format: the printf style format to format the var args into * @... : var args list of parameters to format * * Returns the number of bytes written on success, a value < 0 on error. */ int logprintf(int fd, const char *format, ...) { int ret; va_list ap; va_start(ap, format); ret = _logprintf(fd, format, ap, true); va_end(ap); return ret; } /* * logprintfA: * log to stderr or logfile without checking the log level; indent each * line by a number of spaces * * @fd : the foile descriptor to log to * @indent: number of bytes to indent the string * @format: the printf style format to format the var args into * @... : var args list of parameters to format * * Returns the number of bytes written on success, a value < 0 on error. */ int logprintfA(int fd, unsigned int indent, const char *format, ...) { int ret; va_list ap; char spaces[20]; if (indent) { if (indent > sizeof(spaces) - 1) indent = sizeof(spaces) - 1; memset(spaces, ' ', indent); spaces[indent] = 0; logprintfA(fd, 0, spaces, ""); } va_start(ap, format); ret = _logprintf(fd, format, ap, false); va_end(ap); return ret; } swtpm-0.6.3/src/swtpm/logging.h000066400000000000000000000041251421141172300164300ustar00rootroot00000000000000/* * logging.h -- Logging functions * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_LOGGING_H #define _SWTPM_LOGGING_H #include /* STD???_FILENO */ #include int log_init(const char *filename, bool truncate); int log_init_fd(int fd); int log_set_level(unsigned int level); int logprintf(int fd, const char *format, ...); int logprintfA(int fd, unsigned int indent, const char *format, ...); int log_check_string(const char *); int log_set_prefix(const char *); void log_global_free(void); #endif /* _SWTPM_LOGGING_H */ swtpm-0.6.3/src/swtpm/main.c000066400000000000000000000065511421141172300157260ustar00rootroot00000000000000/* * main.c -- The TPM Emulator's main function * * (c) Copyright IBM Corporation 2014, 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "main.h" #include "swtpm.h" static void usage(FILE *stream, const char *prgname) { fprintf(stream, "TPM emulator with choice of interface.\n" "\n" "Usage: %s socket" #ifdef WITH_CHARDEV "|chardev" #endif #ifdef WITH_CUSE "|cuse" #endif " [options]\n" " %s -v|--version\n" "\n" "Use the --help option to see the help screen for each interface type.\n" "Use the --version options to see version information.\n", prgname,prgname); } int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Missing TPM interface type.\n"); return 1; } if (!strcmp(argv[1], "socket")) { return swtpm_main(argc-1, &argv[1], argv[0], "socket"); #ifdef WITH_CHARDEV } else if (!strcmp(argv[1], "chardev")) { return swtpm_chardev_main(argc-1, &argv[1], argv[0], "chardev"); #endif #ifdef WITH_CUSE } else if (!strcmp(argv[1], "cuse")) { return swtpm_cuse_main(argc-1, &argv[1], argv[0], "cuse"); #endif } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { usage(stdout, argv[0]); } else if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) { fprintf(stdout, "TPM emulator version %d.%d.%d, " "Copyright (c) 2014-2021 IBM Corp.\n", SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); } else { fprintf(stderr, "Unsupported TPM interface type '%s'.\n", argv[1]); usage(stderr, argv[0]); return 1; } return 0; } swtpm-0.6.3/src/swtpm/main.h000066400000000000000000000037611421141172300157330ustar00rootroot00000000000000/* * main.h * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_MAIN_H #define _SWTPM_MAIN_H int swtpm_main(int argc, char **argv, const char *prgname, const char *iface); int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *iface); #ifdef HAVE_SWTPM_CUSE_MAIN int swtpm_cuse_main(int argc, char **argv, const char *prgname, const char *iface); #endif #endif /* _SWTPM_MAIN_H */ swtpm-0.6.3/src/swtpm/mainloop.c000066400000000000000000000264651421141172300166260ustar00rootroot00000000000000/* * mainloop.c -- The TPM Emulator's main processing loop * * (c) Copyright IBM Corporation 2014, 2015, 2016 * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* mainLoop() is the main server loop. It reads a TPM request, processes the ordinal, and writes the response */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swtpm_debug.h" #include "swtpm_io.h" #include "tpmlib.h" #include "locality.h" #include "logging.h" #include "ctrlchannel.h" #include "mainloop.h" #include "utils.h" #include "sys_dependencies.h" /* local variables */ static TPM_MODIFIER_INDICATOR locality; bool tpm_running = false; bool mainloop_terminate; TPM_RESULT mainloop_cb_get_locality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum) { *loc = locality; return TPM_SUCCESS; } int mainLoop(struct mainLoopParams *mlp, int notify_fd) { TPM_RESULT rc = 0; TPM_CONNECTION_FD connection_fd; /* file descriptor for read/write */ unsigned char *command = NULL; /* command buffer */ uint32_t command_length; /* actual length of command bytes */ uint32_t max_command_length; /* command buffer size */ off_t cmd_offset; /* The response buffer is reused for each command. Thus it can grow but never shrink */ unsigned char *rbuffer = NULL; /* actual response bytes */ uint32_t rlength = 0; /* bytes in response buffer */ uint32_t rTotal = 0; /* total allocated bytes */ int ctrlfd; int ctrlclntfd; int sockfd; int ready; struct iovec iov[3]; uint32_t ack = htobe32(0); struct tpm2_resp_prefix respprefix; /* poolfd[] indexes */ enum { DATA_CLIENT_FD = 0, NOTIFY_FD, CTRL_SERVER_FD, CTRL_CLIENT_FD, DATA_SERVER_FD }; TPM_DEBUG("mainLoop:\n"); max_command_length = tpmlib_get_tpm_property(TPMPROP_TPM_BUFFER_MAX) + sizeof(struct tpm2_send_command_prefix); command = malloc(max_command_length); if (!command) { logprintf(STDERR_FILENO, "Could not allocate %u bytes for buffer.\n", max_command_length); return TPM_FAIL; } /* header and trailer that we may send by setting iov_len */ iov[0].iov_base = &respprefix; iov[0].iov_len = 0; iov[2].iov_base = &ack; iov[2].iov_len = 0; connection_fd.fd = -1; ctrlfd = ctrlchannel_get_fd(mlp->cc); ctrlclntfd = ctrlchannel_get_client_fd(mlp->cc); sockfd = SWTPM_IO_GetSocketFD(); if (mlp->startupType != _TPM_ST_NONE) { command_length = tpmlib_create_startup_cmd( mlp->startupType, mlp->tpmversion, command, max_command_length); if (command_length > 0) rc = TPMLIB_Process(&rbuffer, &rlength, &rTotal, command, command_length); if (rc || command_length == 0) { mainloop_terminate = true; if (rc) logprintf(STDERR_FILENO, "Could not send Startup: 0x%x\n", rc); } } while (!mainloop_terminate) { while (rc == 0) { if (mlp->flags & MAIN_LOOP_FLAG_USE_FD) connection_fd.fd = mlp->fd; struct pollfd pollfds[] = { { .fd = connection_fd.fd, .events = POLLIN | POLLHUP, .revents = 0, }, { .fd = notify_fd, .events = POLLIN, .revents = 0, }, { .fd = -1, .events = POLLIN, .revents = 0, } , { .fd = ctrlclntfd, .events = POLLIN | POLLHUP, .revents = 0, } , { /* listen socket for accepting clients */ .fd = -1, .events = POLLIN, .revents = 0, } }; /* only listend for clients if we don't have one */ if (connection_fd.fd < 0) pollfds[DATA_SERVER_FD].fd = sockfd; if (ctrlclntfd < 0) pollfds[CTRL_SERVER_FD].fd = ctrlfd; ready = poll(pollfds, 5, -1); if (ready < 0 && errno == EINTR) continue; if (ready < 0 || (pollfds[NOTIFY_FD].revents & POLLIN) != 0) { SWTPM_IO_Disconnect(&connection_fd); break; } if (pollfds[DATA_CLIENT_FD].revents & (POLLHUP | POLLERR)) { logprintf(STDERR_FILENO, "Data client disconnected\n"); mlp->fd = -1; /* chardev and unixio get this signal, not tcp */ if (mlp->flags & MAIN_LOOP_FLAG_END_ON_HUP) { /* only the chardev terminates here */ mainloop_terminate = true; break; } } if (pollfds[DATA_SERVER_FD].revents & POLLIN) connection_fd.fd = accept(pollfds[DATA_SERVER_FD].fd, NULL, 0); if (pollfds[CTRL_SERVER_FD].revents & POLLIN) ctrlclntfd = accept(ctrlfd, NULL, 0); if (pollfds[CTRL_CLIENT_FD].revents & POLLIN) { ctrlclntfd = ctrlchannel_process_fd(ctrlclntfd, &mainloop_terminate, &locality, &tpm_running, mlp); if (mainloop_terminate) break; } if (pollfds[CTRL_CLIENT_FD].revents & POLLHUP) { if (ctrlclntfd >= 0) close(ctrlclntfd); ctrlclntfd = -1; } if (!(pollfds[DATA_CLIENT_FD].revents & POLLIN)) continue; /* Read the command. The number of bytes is determined by 'paramSize' in the stream */ if (rc == 0) { rc = SWTPM_IO_Read(&connection_fd, command, &command_length, max_command_length); if (rc != 0) { /* connection broke */ SWTPM_IO_Disconnect(&connection_fd); } } cmd_offset = 0; /* Handle optional TCG Header in front of TPM 2 Command */ if (rc == 0 && mlp->tpmversion == TPMLIB_TPM_VERSION_2) { cmd_offset = tpmlib_handle_tcg_tpm2_cmd_header(command, command_length, &locality); if (cmd_offset > 0) { /* send header and trailer */ iov[0].iov_len = sizeof(respprefix); iov[2].iov_len = sizeof(ack); } else { iov[0].iov_len = 0; iov[2].iov_len = 0; } } if (rc == 0) { if (!tpm_running) { tpmlib_write_fatal_error_response(&rbuffer, &rlength, &rTotal, mlp->tpmversion); goto skip_process; } } if (rc == 0) { rlength = 0; /* clear the response buffer */ rc = tpmlib_process(&rbuffer, &rlength, &rTotal, &command[cmd_offset], command_length - cmd_offset, mlp->locality_flags, &locality, mlp->tpmversion); if (rlength) goto skip_process; } if (rc == 0) { rlength = 0; /* clear the response buffer */ rc = TPMLIB_Process(&rbuffer, &rlength, &rTotal, &command[cmd_offset], command_length - cmd_offset); } skip_process: /* write the results */ if (rc == 0) { respprefix.size = htobe32(rlength); iov[1].iov_base = rbuffer; iov[1].iov_len = rlength; SWTPM_IO_Write(&connection_fd, iov, ARRAY_LEN(iov)); } if (!(mlp->flags & MAIN_LOOP_FLAG_KEEP_CONNECTION)) { SWTPM_IO_Disconnect(&connection_fd); break; } } rc = 0; /* A fatal TPM_Process() error should cause the TPM to enter shutdown. IO errors are outside the TPM, so the TPM does not shut down. The main loop should continue to function.*/ if (connection_fd.fd < 0 && mlp->flags & MAIN_LOOP_FLAG_TERMINATE) break; } free(rbuffer); free(command); if (ctrlclntfd >= 0) close(ctrlclntfd); ctrlchannel_set_client_fd(mlp->cc, -1); if (mlp->fd >= 0) { close(mlp->fd); mlp->fd = -1; } return rc; } swtpm-0.6.3/src/swtpm/mainloop.h000066400000000000000000000047741421141172300166320ustar00rootroot00000000000000/* * mainloop.h -- The TPM Emulator's main processing loop * * (c) Copyright IBM Corporation 2014, 2015, 2016 * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* mainLoop() is the main server loop. It reads a TPM request, processes the ordinal, and writes the response */ #ifndef _SWTPM_MAINLOOP_H_ #define _SWTPM_MAINLOOP_H_ #include extern bool mainloop_terminate; extern bool tpm_running; struct mainLoopParams { uint32_t flags; #define MAIN_LOOP_FLAG_TERMINATE (1 << 0) #define MAIN_LOOP_FLAG_USE_FD (1 << 1) #define MAIN_LOOP_FLAG_KEEP_CONNECTION (1 << 2) #define MAIN_LOOP_FLAG_END_ON_HUP (1 << 3) int fd; struct ctrlchannel *cc; uint32_t locality_flags; TPMLIB_TPMVersion tpmversion; uint16_t startupType; /* use TPM 1.2 types */ }; int mainLoop(struct mainLoopParams *mlp, int notify_fd); TPM_RESULT mainloop_cb_get_locality(TPM_MODIFIER_INDICATOR *loc, uint32_t tpmnum); #endif /* _SWTPM_MAINLOOP_H_ */ swtpm-0.6.3/src/swtpm/options.c000066400000000000000000000316211421141172300164710ustar00rootroot00000000000000/* * options.c -- Option parsing * * (c) Copyright IBM Corporation 2014, 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "sys_dependencies.h" #include #include #include #include #include #include #include #include #include "options.h" static void option_error_set(char **error, const char *format, ...) { va_list ap; int ret; va_start(ap, format); ret = vasprintf(error, format, ap); va_end(ap); (void)ret; } /* * option_value_add * Add a option's value that was parsed following a template to the collection * of option values. * @ovs: OptionValues where to add the given value * @optdesc: the template to use for parsing this option * @val: the value to parses as a datatype given in optdesc * @error: Pointer to a pointer for an error message * * Returns 0 on success, -1 on error. */ static int option_value_add(OptionValues *ovs, const OptionDesc optdesc, const char *val, char **error) { int ret = 0; char *endptr = NULL; long int li; long unsigned int lui; struct passwd *passwd; struct group *group; size_t idx = ovs->n_options; ovs->options = realloc(ovs->options, (idx + 1) * sizeof(*ovs->options)); if (!ovs->options) { option_error_set(error, "Out of memory"); return -1; } ovs->n_options = idx + 1; ovs->options[idx].type = optdesc.type; ovs->options[idx].name = optdesc.name; switch (optdesc.type) { case OPT_TYPE_STRING: ovs->options[idx].u.string = strdup(val); if (!ovs->options[idx].u.string) { option_error_set(error, "Out of memory"); return -1; } break; case OPT_TYPE_INT: li = strtol(val, &endptr, 10); if (*endptr != '\0') { option_error_set(error, "invalid number '%s'", val); return -1; } if (li < INT_MIN || li > INT_MAX) { option_error_set(error, "number %li outside valid range", li); } ovs->options[idx].u.integer = li; break; case OPT_TYPE_UINT: lui = strtol(val, &endptr, 10); if (*endptr != '\0') { option_error_set(error, "invalid number '%s'", val); return -1; } if (lui > UINT_MAX) { option_error_set(error, "number %li outside valid range", lui); } ovs->options[idx].u.uinteger = lui; break; case OPT_TYPE_BOOLEAN: if (!strcasecmp(val, "true") || !strcasecmp(val, "1")) { ovs->options[idx].u.boolean = true; } else { ovs->options[idx].u.boolean = false; } break; case OPT_TYPE_MODE_T: lui = strtol(val, &endptr, 8); if (*endptr != '\0') { option_error_set(error, "invalid mode type '%s'", val); return -1; } if (lui > 0777) { option_error_set(error, "mode %s is invalid", val); return -1; } ovs->options[idx].u.mode = (mode_t)lui; break; case OPT_TYPE_UID_T: lui = strtol(val, &endptr, 10); if (*endptr == '\0') { if (lui > UINT_MAX) { option_error_set(error, "uid %s outside valid range", val); return -1; } } else { /* try as a string */ passwd = getpwnam(val); if (!passwd) { option_error_set(error, "User '%s' does not exist.\n", val); return -1; } lui = passwd->pw_uid; } ovs->options[idx].u.uid = (uid_t)lui; break; case OPT_TYPE_GID_T: lui = strtol(val, &endptr, 10); if (*endptr == '\0') { if (lui > UINT_MAX) { option_error_set(error, "gid %s outside valid range", val); return -1; } } else { /* try as a string */ group = getgrnam(val); if (!group) { option_error_set(error, "Group '%s' does not exist.\n", val); return -1; } lui = group->gr_gid; } ovs->options[idx].u.gid = (uid_t)lui; break; } return ret; } /* * options_parse: * Parse the string of options following the template; return the * parsed Options or an error string. * @opts: string containing the comma separated options to parse * @optdesc: template to follow when parsing individual options * @error: Pointer to a pointer for holding an error message * * Returns the parse options, types, and values in OptionValues. */ OptionValues * options_parse(char *opts, const OptionDesc optdesc[], char **error) { char *saveptr; char *tok; int i; OptionValues *ovs = calloc(sizeof(OptionValues), 1); bool found; char *opts_bak; if (!ovs) { option_error_set(error, "Out of memory."); return NULL; } opts_bak = strdup(opts); if (!opts_bak) { option_error_set(error, "Out of memory."); goto error; } saveptr = opts_bak; /* make coverity happy */ tok = strtok_r(opts_bak, ",", &saveptr); while (tok) { size_t toklen = strlen(tok); found = false; i = 0; while (optdesc[i].name) { size_t len = strlen(optdesc[i].name); if (toklen > len + 1 && tok[len] == '=' && !strncmp(optdesc[i].name, tok, len)) { const char *v = &tok[len + 1]; if (option_value_add(ovs, optdesc[i], v, error) < 0) goto error; found = true; break; } else if (!strcmp(optdesc[i].name, tok)) { if (option_value_add(ovs, optdesc[i], "true", error) < 0) goto error; found = true; break; } i++; } if (!found) { option_error_set(error, "Unknown option '%s'", tok); goto error; } tok = strtok_r(NULL, ",", &saveptr); } free(opts_bak); return ovs; error: free(opts_bak); option_values_free(ovs); return NULL; } /* * option_values_free * Free the option values * @ovs: OptionValues structure to free; may be NULL */ void option_values_free(OptionValues *ovs) { size_t i; if (!ovs) return; for (i = 0; i < ovs->n_options; i++) { switch (ovs->options[i].type) { case OPT_TYPE_STRING: free(ovs->options[i].u.string); break; case OPT_TYPE_INT: case OPT_TYPE_UINT: case OPT_TYPE_BOOLEAN: case OPT_TYPE_MODE_T: case OPT_TYPE_UID_T: case OPT_TYPE_GID_T: break; } } free(ovs->options); free(ovs); } /* * Given the name of a string option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed; * If the value is of different type than a string, NULL is returned. */ const char * option_get_string(OptionValues *ovs, const char *name, const char *def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_STRING) return ovs->options[i].u.string; return NULL; } } return def; } /* * Given the name of an int option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than an integer, -1 is returned. */ int option_get_int(OptionValues *ovs, const char *name, int def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_INT) return ovs->options[i].u.integer; return -1; } } return def; } /* * Given the name of an uint option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than an integer, ~0 is returned. */ unsigned int option_get_uint(OptionValues *ovs, const char *name, unsigned int def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_UINT) return ovs->options[i].u.uinteger; return ~0; } } return def; } /* * Given the name of a boolean option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than a boolean, false is returned. */ bool option_get_bool(OptionValues *ovs, const char *name, bool def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_BOOLEAN) return ovs->options[i].u.boolean; return false; } } return def; } /* * Given the name of a mode_t (chmod) option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than a mode_t, ~0 is returned. */ mode_t option_get_mode_t(OptionValues *ovs, const char *name, mode_t def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_MODE_T) return ovs->options[i].u.mode; return ~0; } } return def; } /* * Given the name of a uid_t (chown) option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than a uid_t, -1 is returned. */ uid_t option_get_uid_t(OptionValues *ovs, const char *name, uid_t def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_UID_T) return ovs->options[i].u.uid; return -1; } } return def; } /* * Given the name of a gid_t (chown) option, return the value it received when it * was parsed. * @ovs: The OptionValues * @name: the name of the option * @def: the default value * * Returns the parsed value or the default value if none was parsed * If the value is of different type than a uid_t, -1 is returned. */ gid_t option_get_gid_t(OptionValues *ovs, const char *name, gid_t def) { size_t i; for (i = 0; i < ovs->n_options; i++) { if (!strcmp(name, ovs->options[i].name)) { if (ovs->options[i].type == OPT_TYPE_GID_T) return ovs->options[i].u.gid; return -1; } } return def; } swtpm-0.6.3/src/swtpm/options.h000066400000000000000000000061251421141172300164770ustar00rootroot00000000000000/* * options.h -- Option parsing * * (c) Copyright IBM Corporation 2014. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_OPTIONS_H #define _SWTPM_OPTIONS_H #include #include /* FreeBSD for mode_t */ enum OptionType { OPT_TYPE_STRING, OPT_TYPE_INT, OPT_TYPE_UINT, OPT_TYPE_BOOLEAN, OPT_TYPE_MODE_T, OPT_TYPE_UID_T, OPT_TYPE_GID_T, }; typedef struct { enum OptionType type; const char *name; union { char *string; int integer; unsigned int uinteger; bool boolean; mode_t mode; uid_t uid; gid_t gid; }u; } OptionValue; typedef struct { size_t n_options; OptionValue *options; } OptionValues; typedef struct { const char *name; enum OptionType type; } OptionDesc; #define END_OPTION_DESC \ { \ .name = NULL, \ } OptionValues *options_parse(char *opts, const OptionDesc optdesc[], char **error); void option_values_free(OptionValues *ov); const char *option_get_string(OptionValues *ovs, const char *name, const char *def); int option_get_int(OptionValues *ovs, const char *name, int def); unsigned int option_get_uint(OptionValues *ovs, const char *name, unsigned int def); bool option_get_bool(OptionValues *ovs, const char *name, bool def); mode_t option_get_mode_t(OptionValues *ovs, const char *name, mode_t def); uid_t option_get_uid_t(OptionValues *ovs, const char *name, uid_t def); gid_t option_get_gid_t(OptionValues *ovs, const char *name, gid_t def); #endif /* _SWTPM_OPTIONS_H */ swtpm-0.6.3/src/swtpm/osx.c000066400000000000000000000035101421141172300156030ustar00rootroot00000000000000/* * osx.c -- OS X specifics * * (c) Copyright IBM Corporation 2018. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "osx.h" #if defined __APPLE__ int daemon(int, int); /* OS X deprecates it */ int osx_daemon(int nochdir, int noclose) { return daemon(nochdir, noclose); } #endif /* __APPLE__ */swtpm-0.6.3/src/swtpm/osx.h000066400000000000000000000033271421141172300156160ustar00rootroot00000000000000/* * osx.h -- OS X specifics * * (c) Copyright IBM Corporation 2018. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SWTPM_OSX #define SWTPM_OSX int osx_daemon(int nochdir, int noclose); #endif /* SWTPM_OSX */swtpm-0.6.3/src/swtpm/pidfile.c000066400000000000000000000071241421141172300164130ustar00rootroot00000000000000/* * pidfile.c -- pidfile handling * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include "pidfile.h" #include "logging.h" #include "utils.h" static char *g_pidfile; static int pidfilefd = -1; int pidfile_set(const char *pidfile) { g_pidfile = strdup(pidfile); if (!g_pidfile) { logprintf(STDERR_FILENO, "Out of memory.\n"); return -1; } return 0; } int pidfile_set_fd(int newpidfilefd) { pidfilefd = newpidfilefd; return 0; } /* * pidfile_write: Write the given pid to the pidfile * * @pid: the PID to write * * Returns 0 on success, -1 on failure. */ int pidfile_write(pid_t pid) { int fd; char buffer[32]; ssize_t nwritten; if (g_pidfile) { fd = open(g_pidfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); } else if (pidfilefd >= 0) { fd = pidfilefd; g_pidfile = fd_to_filename(pidfilefd); if (!g_pidfile) goto error; pidfile_set_fd(-1); /* will be closed */ } else { return 0; } if (fd < 0) { logprintf(STDERR_FILENO, "Could not open pidfile %s : %s\n", g_pidfile, strerror(errno)); goto error; } if (snprintf(buffer, sizeof(buffer), "%d", pid) >= (int)sizeof(buffer)) { logprintf(STDERR_FILENO, "Could not write pid to buffer\n"); goto error_close; } nwritten = write_full(fd, buffer, strlen(buffer)); if (nwritten < 0 || nwritten != (ssize_t)strlen(buffer)) { logprintf(STDERR_FILENO, "Could not write to pidfile : %s\n", strerror(errno)); goto error_close; } close(fd); return 0; error_close: close(fd); error: return -1; } /* * pidfile_remove: Remove the pid file * */ void pidfile_remove(void) { if (!g_pidfile) return; unlink(g_pidfile); free(g_pidfile); g_pidfile = NULL; }swtpm-0.6.3/src/swtpm/pidfile.h000066400000000000000000000035211421141172300164150ustar00rootroot00000000000000/* * pidfile.h -- pidfile handling * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_PIDFILE_H_ #define _SWTPM_PIDFILE_H_ int pidfile_set(const char *pidfile); int pidfile_set_fd(int newpidfilefd); int pidfile_write(pid_t pid); void pidfile_remove(void); #endif /* _SWTPM_PIDFILE_H_ */ swtpm-0.6.3/src/swtpm/seccomp_profile.c000066400000000000000000000204461421141172300201520ustar00rootroot00000000000000/* * seccomp_profile.c -- seccomp profile support * * (c) Copyright IBM Corporation 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #ifdef WITH_SECCOMP # include #endif #include "logging.h" #include "utils.h" #include "seccomp_profile.h" #ifdef WITH_SECCOMP static int create_seccomp_profile_add_rules(scmp_filter_ctx ctx, int *syscalls, size_t syscalls_len, unsigned int action) { int ret = 0; unsigned i = 0; uint32_t act = SCMP_ACT_KILL; #ifdef SCMP_ACT_LOG if (action == SWTPM_SECCOMP_ACTION_LOG) act = SCMP_ACT_LOG; #endif for (i = 0; i < syscalls_len; i++) { ret = seccomp_rule_add(ctx, act, syscalls[i], 0); if (ret < 0) { logprintf(STDERR_FILENO, "seccomp_rule_add failed with errno %d: %s\n", -ret, strerror(-ret)); break; } } return ret; } /* * create_seccomp_profile: Build a blacklist of syscalls * * cusetpm: whether to build for the CUSE tpm * action: the seccomp action */ int create_seccomp_profile(bool cusetpm, unsigned int action) { int blacklist[] = { /* high concern */ SCMP_SYS(capset), SCMP_SYS(pivot_root), SCMP_SYS(chroot), SCMP_SYS(settimeofday), SCMP_SYS(clock_adjtime), SCMP_SYS(clock_settime), #ifdef __NR_clock_settime64 SCMP_SYS(clock_settime64), #endif SCMP_SYS(adjtimex), SCMP_SYS(mount), SCMP_SYS(umount2), #ifdef __NR_fsmount SCMP_SYS(fsmount), #endif #ifdef __NR_move_mount SCMP_SYS(move_mount), #endif SCMP_SYS(swapon), SCMP_SYS(swapoff), SCMP_SYS(reboot), SCMP_SYS(tgkill), SCMP_SYS(kexec_load), SCMP_SYS(unshare), SCMP_SYS(setns), SCMP_SYS(kcmp), SCMP_SYS(init_module), SCMP_SYS(finit_module), SCMP_SYS(delete_module), SCMP_SYS(seccomp), SCMP_SYS(kexec_file_load), #ifdef __NR_sysctl SCMP_SYS(sysctl), #endif /* semaphores and messages queues */ SCMP_SYS(semget), SCMP_SYS(semop), SCMP_SYS(shmget), SCMP_SYS(shmat), SCMP_SYS(shmctl), SCMP_SYS(shmdt), SCMP_SYS(msgget), SCMP_SYS(msgsnd), SCMP_SYS(msgrcv), SCMP_SYS(msgctl), SCMP_SYS(mq_open), SCMP_SYS(mq_unlink), SCMP_SYS(mq_timedsend), SCMP_SYS(mq_timedreceive), SCMP_SYS(mq_notify), SCMP_SYS(mq_getsetattr), /* misc */ SCMP_SYS(ptrace), SCMP_SYS(syslog), SCMP_SYS(capget), SCMP_SYS(capset), SCMP_SYS(sigaltstack), SCMP_SYS(personality), SCMP_SYS(sysfs), SCMP_SYS(getpriority), SCMP_SYS(setpriority), SCMP_SYS(sched_setparam), SCMP_SYS(sched_setscheduler), SCMP_SYS(sched_setaffinity), SCMP_SYS(sched_setattr), SCMP_SYS(vhangup), SCMP_SYS(sethostname), SCMP_SYS(setdomainname), SCMP_SYS(quotactl), SCMP_SYS(readahead), SCMP_SYS(lookup_dcookie), SCMP_SYS(add_key), SCMP_SYS(request_key), SCMP_SYS(keyctl), SCMP_SYS(inotify_init), SCMP_SYS(inotify_init1), SCMP_SYS(inotify_add_watch), SCMP_SYS(inotify_rm_watch), SCMP_SYS(splice), SCMP_SYS(tee), SCMP_SYS(vmsplice), SCMP_SYS(signalfd), SCMP_SYS(eventfd), SCMP_SYS(timerfd_settime), #ifdef __NR_timer_settime64 SCMP_SYS(timer_settime64), #endif #ifdef __NR_timerfd_settime64 SCMP_SYS(timerfd_settime64), #endif SCMP_SYS(timerfd_gettime), SCMP_SYS(signalfd4), SCMP_SYS(eventfd2), SCMP_SYS(fanotify_init), SCMP_SYS(fanotify_mark), SCMP_SYS(mknod), SCMP_SYS(mknodat), SCMP_SYS(acct), SCMP_SYS(prlimit64), SCMP_SYS(setrlimit), #ifdef __NR_bpf SCMP_SYS(bpf), #endif #ifdef __NR_copy_filerange SCMP_SYS(copy_filerange), #endif /* xattrs */ SCMP_SYS(setxattr), SCMP_SYS(lsetxattr), SCMP_SYS(fsetxattr), SCMP_SYS(getxattr), SCMP_SYS(lgetxattr), SCMP_SYS(fgetxattr), SCMP_SYS(listxattr), SCMP_SYS(llistxattr), SCMP_SYS(flistxattr), SCMP_SYS(removexattr), SCMP_SYS(lremovexattr), SCMP_SYS(fremovexattr), /* processs forking */ SCMP_SYS(execve), /* io */ SCMP_SYS(iopl), SCMP_SYS(ioperm), SCMP_SYS(io_setup), SCMP_SYS(io_destroy), SCMP_SYS(io_getevents), SCMP_SYS(io_submit), SCMP_SYS(io_cancel), SCMP_SYS(ioprio_set), SCMP_SYS(ioprio_get), /* not implemented, removed */ SCMP_SYS(create_module), SCMP_SYS(get_kernel_syms), SCMP_SYS(query_module), SCMP_SYS(uselib), SCMP_SYS(nfsservctl), SCMP_SYS(getpmsg), SCMP_SYS(putpmsg), SCMP_SYS(afs_syscall), SCMP_SYS(tuxcall), SCMP_SYS(security), SCMP_SYS(set_thread_area), SCMP_SYS(get_thread_area), SCMP_SYS(epoll_ctl_old), SCMP_SYS(epoll_wait_old), SCMP_SYS(vserver), /* privileged */ SCMP_SYS(setuid), SCMP_SYS(setgid), SCMP_SYS(setpgid), SCMP_SYS(setsid), SCMP_SYS(setreuid), SCMP_SYS(setregid), SCMP_SYS(setgroups), SCMP_SYS(setresuid), SCMP_SYS(setresgid), SCMP_SYS(setfsuid), SCMP_SYS(setfsgid) }; /* CUSE TPM needs to clone or fork */ int blacklist_noncuse[] = { SCMP_SYS(clone), SCMP_SYS(fork), SCMP_SYS(vfork), SCMP_SYS(prctl), #ifdef __NR_clone3 SCMP_SYS(clone3), #endif }; scmp_filter_ctx ctx; int ret; if (action == SWTPM_SECCOMP_ACTION_NONE) return 0; ctx = seccomp_init(SCMP_ACT_ALLOW); if (!ctx) { logprintf(STDERR_FILENO, "seccomp_init failed\n"); return -1; } if ((ret = create_seccomp_profile_add_rules(ctx, blacklist, ARRAY_LEN(blacklist), action)) < 0) goto error_seccomp_rule_add; if (!cusetpm && (ret = create_seccomp_profile_add_rules(ctx, blacklist_noncuse, ARRAY_LEN(blacklist_noncuse), action)) < 0) goto error_seccomp_rule_add; if ((ret = seccomp_load(ctx)) < 0) logprintf(STDERR_FILENO, "seccomp_load failed with errno %d: %s\n", -ret, strerror(-ret)); error_seccomp_rule_add: seccomp_release(ctx); return ret; } #endif swtpm-0.6.3/src/swtpm/seccomp_profile.h000066400000000000000000000042741421141172300201600ustar00rootroot00000000000000/* * seccomp_profile.h -- seccomp profile suppport * * (c) Copyright IBM Corporation 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SWTPM_SECCOMP_H #define SWTPM_SECCOMP_H #include "config.h" #include /* action to take in seccomp profile */ #define SWTPM_SECCOMP_ACTION_KILL 1 #define SWTPM_SECCOMP_ACTION_LOG 2 #define SWTPM_SECCOMP_ACTION_NONE 3 /* = no profile */ #ifdef WITH_SECCOMP int create_seccomp_profile(bool cusetpm, unsigned int action); #else static inline int create_seccomp_profile(bool cusetpm __attribute__((unused)), unsigned int action __attribute__((unused))) { return 0; } #endif #endif /* SWTPM_SECCOMP_H */ swtpm-0.6.3/src/swtpm/server.c000066400000000000000000000053601421141172300163050ustar00rootroot00000000000000/* * server.c -- server parameters * * (c) Copyright IBM Corporation 2016. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "logging.h" #include "server.h" struct server { int fd; unsigned int flags; char *sockpath; /* for UnixIO socket */ }; struct server *server_new(int fd, unsigned int flags, const char *sockpath) { struct server *c = calloc(1, sizeof(struct server)); if (!c) { logprintf(STDERR_FILENO, "Out of memory"); return NULL; } c->fd = fd; c->flags = flags; if (sockpath) { c->sockpath = strdup(sockpath); if (!c->sockpath) { logprintf(STDERR_FILENO, "Out of memory"); free(c); c = NULL; } } return c; } int server_get_fd(struct server *c) { return c->fd; } int server_set_fd(struct server *c, int fd) { int oldfd = c->fd; c->fd = fd; return oldfd; } unsigned int server_get_flags(struct server *c) { return c->flags; } void server_free(struct server *c) { if (!c) return; if (c->fd >= 0) close(c->fd); if (c->sockpath) { unlink(c->sockpath); free(c->sockpath); } free(c); } swtpm-0.6.3/src/swtpm/server.h000066400000000000000000000040701421141172300163070ustar00rootroot00000000000000/* * server.h -- server parameters * * (c) Copyright IBM Corporation 2016. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_SERVER_H_ #define _SWTPM_SERVER_H_ struct server; #define SERVER_FLAG_DISCONNECT (1 << 0) #define SERVER_FLAG_FD_GIVEN (1 << 1) struct server *server_new(int fd, unsigned int flags, const char *sockpath); int server_get_fd(struct server *c); int server_set_fd(struct server *c, int fd); unsigned int server_get_flags(struct server *c); void server_free(struct server *s); #endif /* _SWTPM_SERVER_H_ */ swtpm-0.6.3/src/swtpm/swtpm.c000066400000000000000000000463561421141172300161630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Main Program */ /* Written by Ken Goldman, Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2006, 2010, 2016, 2019. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "swtpm_debug.h" #include "swtpm_io.h" #include "swtpm_nvfile.h" #include "server.h" #include "common.h" #include "logging.h" #include "pidfile.h" #include "tpmlib.h" #include "utils.h" #include "mainloop.h" #include "ctrlchannel.h" #include "tpmstate.h" #include "sys_dependencies.h" #include "osx.h" #include "seccomp_profile.h" #include "options.h" #include "capabilities.h" /* local variables */ static int notify_fd[2] = {-1, -1}; static struct libtpms_callbacks callbacks = { .sizeOfStruct = sizeof(struct libtpms_callbacks), .tpm_nvram_init = SWTPM_NVRAM_Init, .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData, .tpm_nvram_storedata = SWTPM_NVRAM_StoreData, .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName, .tpm_io_init = SWTPM_IO_Init, .tpm_io_getlocality = mainloop_cb_get_locality, }; static void sigterm_handler(int sig __attribute__((unused))) { TPM_DEBUG("Terminating...\n"); if (write(notify_fd[1], "T", 1) < 0) { logprintf(STDERR_FILENO, "Error: sigterm notification failed: %s\n", strerror(errno)); } mainloop_terminate = true; } static void usage(FILE *file, const char *prgname, const char *iface) { fprintf(file, "Usage: %s %s [options]\n" "\n" "The following options are supported:\n" "\n" "-p|--port : use the given port\n" "-f|--fd : use the given socket file descriptor\n" "-t|--terminate : terminate the TPM once a connection has been lost\n" "-d|--daemon : daemonize the TPM\n" "--ctrl type=[unixio|tcp][,path=][,port=[,bindaddr=address[,ifname=ifname]]][,fd=|clientfd=][,mode=0...][,uid=uid][,gid=gid]\n" " : TPM control channel using either UnixIO or TCP sockets;\n" " the path is only valid for Unixio channels; the port must\n" " be given in case the type is TCP; the TCP socket is bound\n" " to 127.0.0.1 by default and other bind addresses can be\n" " given with the bindaddr parameter; if fd is provided,\n" " it will be treated as a server socket and used for \n" " accepting client connections; if clientfd is provided,\n" " it will be treaded as client connection;\n" " NOTE: fd and clientfd are mutually exclusive and clientfd\n" " is only valid for UnixIO channels\n" " mode allows a user to set the file mode bits of a Unixio socket;\n" " the value must be given in octal number format\n" " uid and gid set the ownership of the Unixio socket's file;\n" "--migration-key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " when it is retrieved from the TPM via ioctls;\n" " Setting this key ensures that the TPM's state will always\n" " be encrypted when migrated\n" "--migration-key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--log file=|fd=[,level=n][,prefix=][,truncate]\n" " : write the TPM's log into the given file rather than\n" " to the console; provide '-' for path to avoid logging\n" " log level 5 and higher will enable libtpms logging;\n" " all logged output will be prefixed with prefix;\n" " the log file can be reset (truncate)\n" "--key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " files; use the given mode for the block encryption;\n" " the key is to be provided as a hex string or in binary\n" " format; the keyfile can be automatically removed using\n" " the remove parameter\n" "--key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--locality [reject-locality-4][,allow-set-locality]\n" " : reject-locality-4: reject any command in locality 4\n" " allow-set-locality: accept SetLocality command\n" "--pid file=|fd=\n" " : write the process ID into the given file\n" "--tpmstate dir=[,mode=0...]\n" " : set the directory where the TPM's state will be written\n" " into; the TPM_PATH environment variable can be used\n" " instead;\n" " mode allows a user to set the file mode bits of the state files;\n" " the default mode is 0640;\n" "--server [type=tcp][,port=port[,bindaddr=address[,ifname=ifname]]][,fd=fd][,disconnect]\n" " : Expect TCP connections on the given port;\n" " if fd is provided, packets will be read from it directly;\n" " the disconnect parameter closes the connection after\n" " sending a response back to the client; the TCP socket is\n" " bound to 127.0.0.1 by default and other bind addresses\n" " can be given with the bindaddr parameter\n" "--server type=unixio[,path=path][,fd=fd][,mode=0...][,uid=uid][,gid=gid]\n" " : Expect UnixIO connections on the given path; if fd is\n" " provided, packets will be read from it directly;\n" " mode allows a user to set the file mode bits of the socket; the\n" " value must be given in octal number format;\n" " uid and gid set the ownership of the Unixio socket's file;\n" "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel;\n" " startup-...: send Startup command with this type;\n" "-r|--runas : change to the given user\n" "--tpm2 : choose TPM2 functionality\n" #ifdef WITH_SECCOMP # ifndef SCMP_ACT_LOG "--seccomp action=none|kill\n" # else "--seccomp action=none|kill|log\n" # endif " : Choose the action of the seccomp profile when a\n" " blacklisted syscall is executed; default is kill\n" #endif "--print-capabilites\n" " : print capabilities and terminate\n" "-h|--help : display this help screen and terminate\n" "\n", prgname, iface); } static void swtpm_cleanup(struct ctrlchannel *cc, struct server *server) { pidfile_remove(); ctrlchannel_free(cc); server_free(server); log_global_free(); tpmstate_global_free(); SWTPM_NVRAM_Shutdown(); } int swtpm_main(int argc, char **argv, const char *prgname, const char *iface) { TPM_RESULT rc = 0; int daemonize = FALSE; int opt, longindex, ret; struct stat statbuf; struct mainLoopParams mlp = { .cc = NULL, .flags = 0, .fd = -1, .locality_flags = 0, .tpmversion = TPMLIB_TPM_VERSION_1_2, .startupType = _TPM_ST_NONE, }; struct server *server = NULL; unsigned long val; char *end_ptr; char buf[20]; char *keydata = NULL; char *migkeydata = NULL; char *logdata = NULL; char *piddata = NULL; char *localitydata = NULL; char *tpmstatedata = NULL; char *ctrlchdata = NULL; char *serverdata = NULL; char *flagsdata = NULL; char *seccompdata = NULL; char *runas = NULL; bool need_init_cmd = true; #ifdef DEBUG time_t start_time; #endif unsigned int seccomp_action; bool printcapabilities = false; static struct option longopts[] = { {"daemon" , no_argument, 0, 'd'}, {"help" , no_argument, 0, 'h'}, {"port" , required_argument, 0, 'p'}, {"fd" , required_argument, 0, 'f'}, {"server" , required_argument, 0, 'c'}, {"runas" , required_argument, 0, 'r'}, {"terminate" , no_argument, 0, 't'}, {"locality" , required_argument, 0, 'L'}, {"log" , required_argument, 0, 'l'}, {"key" , required_argument, 0, 'k'}, {"migration-key", required_argument, 0, 'K'}, {"pid" , required_argument, 0, 'P'}, {"tpmstate" , required_argument, 0, 's'}, {"ctrl" , required_argument, 0, 'C'}, {"flags" , required_argument, 0, 'F'}, {"tpm2" , no_argument, 0, '2'}, #ifdef WITH_SECCOMP {"seccomp" , required_argument, 0, 'S'}, #endif {"print-capabilities" , no_argument, 0, 'a'}, {NULL , 0 , 0, 0 }, }; log_set_prefix("swtpm: "); while (TRUE) { opt = getopt_long(argc, argv, "dhp:f:tr:", longopts, &longindex); if (opt == -1) break; switch (opt) { case 'd': daemonize = TRUE; break; case 'p': errno = 0; val = strtoul(optarg, &end_ptr, 0); if (val != (unsigned int)val || errno || end_ptr[0] != '\0') { logprintf(STDERR_FILENO, "Cannot parse socket port number '%s'.\n", optarg); exit(EXIT_FAILURE); } if (val >= 0x10000) { logprintf(STDERR_FILENO, "Port is outside valid range.\n"); exit(EXIT_FAILURE); } snprintf(buf, sizeof(buf), "%lu", val); if (setenv("TPM_PORT", buf, 1) != 0) { logprintf(STDERR_FILENO, "Could not set port: %s\n", strerror(errno)); exit(EXIT_FAILURE); } serverdata = "type=tcp,disconnect"; break; case 'f': errno = 0; val = strtoul(optarg, &end_ptr, 10); if (val != (unsigned int)val || errno || end_ptr[0] != '\0') { logprintf(STDERR_FILENO, "Cannot parse socket file descriptor.\n"); exit(EXIT_FAILURE); } mlp.fd = val; if (fstat(mlp.fd, &statbuf) != 0) { logprintf(STDERR_FILENO, "Cannot stat file descriptor: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* * test for wrong file types; anonymous fd's do not seem to be any of the wrong * ones but are also not character devices */ if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { logprintf(STDERR_FILENO, "Given file descriptor type is not supported.\n"); exit(EXIT_FAILURE); } mlp.flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION; SWTPM_IO_SetSocketFD(mlp.fd); break; case 'c': serverdata = optarg; break; case 't': mlp.flags |= MAIN_LOOP_FLAG_TERMINATE; break; case 'k': keydata = optarg; break; case 'K': migkeydata = optarg; break; case 'l': logdata = optarg; break; case 'P': piddata = optarg; break; case 's': tpmstatedata = optarg; break; case 'C': ctrlchdata = optarg; break; case 'L': localitydata = optarg; break; case 'F': flagsdata = optarg; break; case '2': mlp.tpmversion = TPMLIB_TPM_VERSION_2; break; case 'h': usage(stdout, prgname, iface); exit(EXIT_SUCCESS); case 'a': printcapabilities = true; break; case 'r': runas = optarg; break; case 'S': seccompdata = optarg; break; default: usage(stderr, prgname, iface); exit(EXIT_FAILURE); } } if (optind < argc) { logprintf(STDERR_FILENO, "Unknown parameter '%s'\n", argv[optind]); exit(EXIT_FAILURE); } if (mlp.fd >= 0 && mlp.fd < 3) { /* no std{in,out,err} */ logprintf(STDERR_FILENO, "Error: Cannot accept file descriptors with values 0, 1, or 2\n"); exit(EXIT_FAILURE); } /* * choose the TPM version early so that getting/setting * buffer size works. */ if (TPMLIB_ChooseTPMVersion(mlp.tpmversion) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not choose TPM version.\n"); exit(EXIT_FAILURE); } if (printcapabilities) { ret = capabilities_print_json(false); exit(ret ? EXIT_FAILURE : EXIT_SUCCESS); } if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc) < 0 || handle_server_options(serverdata, &server) < 0) { goto exit_failure; } /* change process ownership before accessing files */ if (runas) { if (change_process_owner(runas) < 0) goto exit_failure; } SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion); if (handle_log_options(logdata) < 0 || handle_key_options(keydata) < 0 || handle_migration_key_options(migkeydata) < 0 || handle_pid_options(piddata) < 0 || handle_locality_options(localitydata, &mlp.locality_flags) < 0 || handle_tpmstate_options(tpmstatedata) < 0 || handle_seccomp_options(seccompdata, &seccomp_action) < 0 || handle_flags_options(flagsdata, &need_init_cmd, &mlp.startupType) < 0) { goto exit_failure; } if (server) { if (server_get_fd(server) >= 0) { mlp.fd = server_set_fd(server, -1); SWTPM_IO_SetSocketFD(mlp.fd); } mlp.flags |= MAIN_LOOP_FLAG_KEEP_CONNECTION; if ((server_get_flags(server) & SERVER_FLAG_DISCONNECT)) mlp.flags &= ~MAIN_LOOP_FLAG_KEEP_CONNECTION; if ((server_get_flags(server) & SERVER_FLAG_FD_GIVEN)) mlp.flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD; } if (daemonize) { #ifdef __APPLE__ if (0 != osx_daemon(1, 0)) { #else if (0 != daemon(1, 0)) { #endif logprintf(STDERR_FILENO, "Error: Could not daemonize.\n"); goto exit_failure; } } if (pidfile_write(getpid()) < 0) { goto exit_failure; } setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe */ #ifdef DEBUG /* initialization */ start_time = time(NULL); #endif TPM_DEBUG("main: Initializing TPM at %s", ctime(&start_time)); tpmlib_debug_libtpms_parameters(mlp.tpmversion); if ((rc = tpmlib_register_callbacks(&callbacks))) goto error_no_tpm; if (!need_init_cmd) { if ((rc = tpmlib_start(0, mlp.tpmversion))) goto error_no_tpm; tpm_running = true; } if (install_sighandlers(notify_fd, sigterm_handler) < 0) goto error_no_sighandlers; if (create_seccomp_profile(false, seccomp_action) < 0) goto error_seccomp_profile; rc = mainLoop(&mlp, notify_fd[0]); error_seccomp_profile: uninstall_sighandlers(); error_no_sighandlers: TPMLIB_Terminate(); error_no_tpm: close(notify_fd[0]); notify_fd[0] = -1; close(notify_fd[1]); notify_fd[1] = -1; swtpm_cleanup(mlp.cc, server); /* Fatal initialization errors cause the program to abort */ if (rc == 0) { exit(EXIT_SUCCESS); } else { TPM_DEBUG("main: TPM initialization failure %08x, exiting\n", rc); exit(EXIT_FAILURE); } exit_failure: swtpm_cleanup(mlp.cc, server); exit(EXIT_FAILURE); } swtpm-0.6.3/src/swtpm/swtpm_aes.c000066400000000000000000000250211421141172300167750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Dependent Crypto */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_crypto_freebl.c 4655 2011-12-21 21:03:15Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include "swtpm_aes.h" #include "logging.h" #define printf(X ...) /* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to 'encrypt_data' The stream is padded as per PKCS#7 / RFC2630 'encrypt_data' must be free by the caller */ TPM_RESULT SWTPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ uint32_t *encrypt_length, /* output */ const unsigned char *decrypt_data, /* input */ uint32_t decrypt_length, /* input */ const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, /* input */ const unsigned char *u_ivec, /* input */ uint32_t u_ivec_length) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; unsigned char *decrypt_data_pad; unsigned char ivec[SWTPM_AES256_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; AES_KEY key; size_t userKeyLength = tpm_symmetric_key_token->userKeyLength; printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); decrypt_data_pad = NULL; /* freed @1 */ if (rc == 0) { if (u_ivec != NULL && u_ivec_length != userKeyLength) { printf("TPM_SymmetricKeyData_Encrypt: IV is %u bytes, " "but expected %u bytes\n", u_ivec_length, tpm_symmetric_key_token->userKeyLength); rc = TPM_ENCRYPT_ERROR; } else { if (u_ivec) { /* copy user-provided IV */ memcpy(ivec, u_ivec, u_ivec_length); } else { memset(ivec, 0, sizeof(ivec)); } } } if (rc == 0) { /* calculate the pad length and padded data length */ pad_length = userKeyLength - (decrypt_length % userKeyLength); *encrypt_length = decrypt_length + pad_length; printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", *encrypt_length, pad_length); /* allocate memory for the encrypted response */ *encrypt_data = malloc(*encrypt_length); if (!*encrypt_data) { logprintf(STDERR_FILENO, "Could not allocated %u bytes.\n", *encrypt_length); rc = TPM_SIZE; } } /* allocate memory for the padded decrypted data */ if (rc == 0) { decrypt_data_pad = malloc(*encrypt_length); if (!decrypt_data_pad) { logprintf(STDERR_FILENO, "Could not allocated %u bytes.\n", *encrypt_length); rc = TPM_SIZE; } } if (rc == 0) { memset(&key, 0, sizeof(key)); /* coverity */ if (AES_set_encrypt_key(tpm_symmetric_key_data->userKey, userKeyLength * 8, &key) < 0) { rc = TPM_FAIL; } } /* pad the decrypted clear text data */ if (rc == 0) { /* unpadded original data */ memcpy(decrypt_data_pad, decrypt_data, decrypt_length); /* last gets pad = pad length */ memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); /* encrypt the padded input to the output */ //TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); AES_cbc_encrypt(decrypt_data_pad, *encrypt_data, *encrypt_length, &key, ivec, AES_ENCRYPT); //TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); } free(decrypt_data_pad); /* @1 */ return rc; } /* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to 'decrypt_data' The stream must be padded as per PKCS#7 / RFC2630 decrypt_data must be free by the caller */ TPM_RESULT SWTPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ uint32_t *decrypt_length, /* output */ const unsigned char *encrypt_data, /* input */ uint32_t encrypt_length, /* input */ const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, /* input */ const unsigned char *u_ivec, /* input */ uint32_t u_ivec_length) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; uint32_t i; unsigned char *pad_data; unsigned char ivec[SWTPM_AES256_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; AES_KEY key; size_t userKeyLength = tpm_symmetric_key_token->userKeyLength; printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); /* sanity check encrypted length */ if (rc == 0) { if (encrypt_length < userKeyLength) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { if (u_ivec != NULL && u_ivec_length != userKeyLength) { printf("TPM_SymmetricKeyData_Decrypt: IV is %u bytes, " "but expected %u bytes\n", u_ivec_length, userKeyLength); rc = TPM_DECRYPT_ERROR; } else { if (u_ivec) { /* copy user-provided IV */ memcpy(ivec, u_ivec, u_ivec_length); } else { memset(ivec, 0, sizeof(ivec)); } } } /* allocate memory for the padded decrypted data */ if (rc == 0) { *decrypt_data = malloc(encrypt_length); if (!*decrypt_data) { logprintf(STDERR_FILENO, "Could not allocated %u bytes.\n", encrypt_length); rc = TPM_SIZE; } } if (rc == 0) { memset(&key, 0, sizeof(key)); /* coverity */ if (AES_set_decrypt_key(tpm_symmetric_key_data->userKey, userKeyLength * 8, &key) < 0) { rc = TPM_FAIL; } } /* decrypt the input to the padded output */ if (rc == 0) { /* decrypt the padded input to the output */ //TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); AES_cbc_encrypt(encrypt_data, *decrypt_data, encrypt_length, &key, ivec, AES_DECRYPT); //TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); } /* get the pad length */ if (rc == 0) { /* get the pad length from the last byte */ pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); /* sanity check the pad length */ printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); if ((pad_length == 0) || (pad_length > userKeyLength)) { printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* get the unpadded length */ *decrypt_length = encrypt_length - pad_length; /* pad starting point */ pad_data = *decrypt_data + *decrypt_length; /* sanity check the pad */ for (i = 0 ; i < pad_length ; i++, pad_data++) { if (*pad_data != pad_length) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", *pad_data, i); rc = TPM_DECRYPT_ERROR; } } } return rc; } swtpm-0.6.3/src/swtpm/swtpm_aes.h000066400000000000000000000055441421141172300170120ustar00rootroot00000000000000/* * swtpm_aes.h * * Author: Stefan Berger stefanb@us.ibm.com * * * (c) Copyright IBM Corporation 2014. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_AES_H_ #define _SWTPM_AES_H_ #include #define SWTPM_AES128_BLOCK_SIZE 16 #define SWTPM_AES256_BLOCK_SIZE 32 typedef struct tdTPM_SYMMETRIC_KEY_DATA { unsigned char userKey[SWTPM_AES256_BLOCK_SIZE]; size_t userKeyLength; } TPM_SYMMETRIC_KEY_DATA; TPM_RESULT SWTPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, uint32_t *encrypt_length, const unsigned char *decrypt_data, uint32_t decrypt_length, const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, const unsigned char *ivec, uint32_t ivec_length); TPM_RESULT SWTPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, uint32_t *decrypt_length, const unsigned char *encrypt_data, uint32_t encrypt_length, const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, const unsigned char *ivec, uint32_t ivec_length); #endif /* _SWTPM_AES_H_ */ swtpm-0.6.3/src/swtpm/swtpm_chardev.c000066400000000000000000000470741421141172300176550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Main Program */ /* Written by Ken Goldman, Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2006, 2010, 2015, 2016, 2019 */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "main.h" #include "swtpm_debug.h" #include "swtpm_io.h" #include "swtpm_nvfile.h" #include "common.h" #include "locality.h" #include "logging.h" #include "pidfile.h" #include "tpmlib.h" #include "utils.h" #include "ctrlchannel.h" #include "mainloop.h" #ifdef WITH_VTPM_PROXY #include "vtpm_proxy.h" #endif #include "tpmstate.h" #include "osx.h" #include "seccomp_profile.h" #include "options.h" #include "capabilities.h" /* local variables */ static int notify_fd[2] = {-1, -1}; static struct libtpms_callbacks callbacks = { .sizeOfStruct = sizeof(struct libtpms_callbacks), .tpm_nvram_init = SWTPM_NVRAM_Init, .tpm_nvram_loaddata = SWTPM_NVRAM_LoadData, .tpm_nvram_storedata = SWTPM_NVRAM_StoreData, .tpm_nvram_deletename = SWTPM_NVRAM_DeleteName, .tpm_io_init = NULL, .tpm_io_getlocality = mainloop_cb_get_locality, }; static void sigterm_handler(int sig __attribute__((unused))) { TPM_DEBUG("Terminating...\n"); if (write(notify_fd[1], "T", 1) < 0) { logprintf(STDERR_FILENO, "Error: sigterm notification failed: %s\n", strerror(errno)); } mainloop_terminate = true; } #ifdef WITH_VTPM_PROXY static int create_vtpm_proxy(struct vtpm_proxy_new_dev *vtpm_new_dev, int *_errno) { int fd, n, ret = 0; fd = open("/dev/vtpmx", O_RDWR); if (fd < 0) { logprintf(STDERR_FILENO, "Could not open /dev/vtpmx: %s\n", strerror(errno)); *_errno = errno; return -1; } n = ioctl(fd, VTPM_PROXY_IOC_NEW_DEV, vtpm_new_dev); if (n) { logprintf(STDERR_FILENO, "Ioctl to create vtpm proxy failed: %s\n", strerror(errno)); *_errno = errno; ret = -1; } close(fd); return ret; } #endif static void usage(FILE *file, const char *prgname, const char *iface) { fprintf(file, "Usage: %s %s [options]\n" "\n" "The following options are supported:\n" "\n" "-c|--chardev \n" " : use the given character device\n" "-f|--fd : use the given character device file descriptor\n" "-d|--daemon : daemonize the TPM\n" "--ctrl type=[unixio|tcp][,path=][,port=[,bindaddr=address[,ifname=ifname]]][,fd=][,mode=0...][,uid=uid][,gid=gid]\n" " : TPM control channel using either UnixIO or TCP sockets;\n" " the path is only valid for Unixio channels; the port must\n" " be given in case the type is TCP; the TCP socket is bound\n" " to 127.0.0.1 by default and other bind addresses can be\n" " given with the bindaddr parameter; if fd is provided,\n" " it will be treated as a server socket and used for \n" " accepting client connections; if clientfd is provided,\n" " it will be treaded as client connection;\n" " NOTE: fd and clientfd are mutually exclusive and \n" " clientfd is only valid for UnixIO channels\n" " mode allows a user to set the file mode bits of a Unixio socket;\n" " the value must be given in octal number format\n" " uid and gid set the ownership of the Unixio socket's file;\n" "--migration-key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " when it is retrieved from the TPM via ioctls;\n" " Setting this key ensures that the TPM's state will always\n" " be encrypted when migrated\n" "--migration-key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--log file=|fd=[,level=n][,prefix=][,truncate]\n" " : write the TPM's log into the given file rather than\n" " to the console; provide '-' for path to avoid logging\n" " log level 5 and higher will enable libtpms logging;\n" " all logged output will be prefixed with prefix;\n" " the log file can be reset (truncate)\n" "--key file=|fd=[,mode=aes-cbc|aes-256-cbc][,format=hex|binary][,remove=[true|false]]\n" " : use an AES key for the encryption of the TPM's state\n" " files; use the given mode for the block encryption;\n" " the key is to be provided as a hex string or in binary\n" " format; the keyfile can be automatically removed using\n" " the remove parameter\n" "--key pwdfile=|pwdfd=[,mode=aes-cbc|aes-256-cbc][,remove=[true|false]][,kdf=sha512|pbkdf2]\n" " : provide a passphrase in a file; the AES key will be\n" " derived from this passphrase; default kdf is PBKDF2\n" "--pid file=|fd=\n" " : write the process ID into the given file\n" "--tpmstate dir=[,mode=0...]\n" " : set the directory where the TPM's state will be written\n" " into; the TPM_PATH environment variable can be used\n" " instead;\n" " mode allows a user to set the file mode bits of the state files;\n" " the default mode is 0640;\n" "-r|--runas : change to the given user\n" #ifdef WITH_VTPM_PROXY "--vtpm-proxy : spawn a Linux vTPM proxy driver device and read TPM\n" #endif " command from its anonymous file descriptor\n" "--locality [reject-locality-4][,allow-set-locality]\n" " : reject-locality-4: reject any command in locality 4\n" " allow-set-locality: accept SetLocality command\n" "--flags [not-need-init][,startup-clear|startup-state|startup-deactivated|startup-none]\n" " : not-need-init: commands can be sent without needing to\n" " send an INIT via control channel; not needed when using\n" " --vtpm-proxy\n" " startup-...: send Startup command with this type;\n" " when --vtpm-proxy is used, startup-clear is used\n" "--tpm2 : choose TPM2 functionality\n" #ifdef WITH_SECCOMP # ifndef SCMP_ACT_LOG "--seccomp action=none|kill\n" # else "--seccomp action=none|kill|log\n" # endif " : Choose the action of the seccomp profile when a\n" " blacklisted syscall is executed; default is kill\n" #endif "--print-capabilites\n" " : print capabilities and terminate\n" "-h|--help : display this help screen and terminate\n" "\n", prgname, iface); } static void swtpm_cleanup(struct ctrlchannel *cc) { pidfile_remove(); ctrlchannel_free(cc); log_global_free(); tpmstate_global_free(); SWTPM_NVRAM_Shutdown(); } #ifdef WITH_VTPM_PROXY static int swtpm_chardev_create_vtpm_proxy(struct mainLoopParams *mlp, bool *need_init_cmd) { struct vtpm_proxy_new_dev vtpm_new_dev = { .flags = 0, }; int _errno; if (mlp->tpmversion == TPMLIB_TPM_VERSION_2) vtpm_new_dev.flags = VTPM_PROXY_FLAG_TPM2; /* Will be adjusted for TPM 2 */ mlp->startupType = TPM_ST_CLEAR; *need_init_cmd = false; if (mlp->fd >= 0) { logprintf(STDERR_FILENO, "Cannot use vTPM proxy with a provided device.\n"); return -1; } if (create_vtpm_proxy(&vtpm_new_dev, &_errno)) return -1; mlp->fd = vtpm_new_dev.fd; mlp->flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD; SWTPM_IO_SetSocketFD(mlp->fd); fprintf(stdout, "New TPM device: /dev/tpm%u (major/minor = %u/%u)\n", vtpm_new_dev.tpm_num, vtpm_new_dev.major, vtpm_new_dev.minor); mlp->locality_flags |= LOCALITY_FLAG_ALLOW_SETLOCALITY; return 0; } #endif int swtpm_chardev_main(int argc, char **argv, const char *prgname, const char *iface) { TPM_RESULT rc = 0; int daemonize = FALSE; int opt, longindex, ret; struct stat statbuf; struct mainLoopParams mlp = { .cc = NULL, .fd = -1, .flags = 0, .locality_flags = 0, .tpmversion = TPMLIB_TPM_VERSION_1_2, .startupType = _TPM_ST_NONE, }; unsigned long val; char *end_ptr; char *keydata = NULL; char *migkeydata = NULL; char *logdata = NULL; char *piddata = NULL; char *localitydata = NULL; char *tpmstatedata = NULL; char *ctrlchdata = NULL; char *flagsdata = NULL; char *seccompdata = NULL; char *runas = NULL; #ifdef WITH_VTPM_PROXY bool use_vtpm_proxy = false; #endif #ifdef DEBUG time_t start_time; #endif bool need_init_cmd = true; unsigned int seccomp_action; bool printcapabilities = false; static struct option longopts[] = { {"daemon" , no_argument, 0, 'd'}, {"help" , no_argument, 0, 'h'}, {"chardev" , required_argument, 0, 'c'}, {"fd" , required_argument, 0, 'f'}, {"runas" , required_argument, 0, 'r'}, {"locality" , required_argument, 0, 'L'}, {"log" , required_argument, 0, 'l'}, {"key" , required_argument, 0, 'k'}, {"migration-key", required_argument, 0, 'K'}, {"pid" , required_argument, 0, 'P'}, {"tpmstate" , required_argument, 0, 's'}, {"ctrl" , required_argument, 0, 'C'}, {"flags" , required_argument, 0, 'F'}, #ifdef WITH_VTPM_PROXY {"vtpm-proxy", no_argument, 0, 'v'}, #endif {"tpm2" , no_argument, 0, '2'}, #ifdef WITH_SECCOMP {"seccomp" , required_argument, 0, 'S'}, #endif {"print-capabilities" , no_argument, 0, 'a'}, {NULL , 0 , 0, 0 }, }; log_set_prefix("swtpm: "); while (TRUE) { opt = getopt_long(argc, argv, "dhc:f:r:", longopts, &longindex); if (opt == -1) break; switch (opt) { case 'd': daemonize = TRUE; break; case 'c': if (mlp.fd >= 0) continue; mlp.fd = open(optarg, O_RDWR); if (mlp.fd < 0) { logprintf(STDERR_FILENO, "Cannot open %s: %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } mlp.flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD; SWTPM_IO_SetSocketFD(mlp.fd); break; case 'f': if (mlp.fd >= 0) continue; errno = 0; val = strtoul(optarg, &end_ptr, 10); if (val != (unsigned int)val || errno || end_ptr[0] != '\0') { logprintf(STDERR_FILENO, "Cannot parse character device file descriptor.\n"); exit(EXIT_FAILURE); } mlp.fd = val; if (fstat(mlp.fd, &statbuf) != 0) { logprintf(STDERR_FILENO, "Cannot stat file descriptor: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* * test for wrong file types; anonymous fd's do not seem to be any of the wrong * ones but are also not character devices */ if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) { logprintf(STDERR_FILENO, "Given file descriptor type is not supported.\n"); exit(EXIT_FAILURE); } mlp.flags |= MAIN_LOOP_FLAG_TERMINATE | MAIN_LOOP_FLAG_USE_FD; SWTPM_IO_SetSocketFD(mlp.fd); break; case 'k': keydata = optarg; break; case 'K': migkeydata = optarg; break; case 'l': logdata = optarg; break; case 'P': piddata = optarg; break; case 's': tpmstatedata = optarg; break; case 'C': ctrlchdata = optarg; break; case 'L': localitydata = optarg; break; case 'F': flagsdata = optarg; break; case '2': mlp.tpmversion = TPMLIB_TPM_VERSION_2; break; case 'h': usage(stdout, prgname, iface); exit(EXIT_SUCCESS); case 'a': printcapabilities = true; break; case 'r': runas = optarg; break; #ifdef WITH_VTPM_PROXY case 'v': use_vtpm_proxy = true; break; #endif case 'S': seccompdata = optarg; break; default: usage(stderr, prgname, iface); exit(EXIT_FAILURE); } } if (optind < argc) { logprintf(STDERR_FILENO, "Unknown parameter '%s'\n", argv[optind]); exit(EXIT_FAILURE); } if (handle_locality_options(localitydata, &mlp.locality_flags) < 0) exit(EXIT_FAILURE); #ifdef WITH_VTPM_PROXY if (use_vtpm_proxy) { if (swtpm_chardev_create_vtpm_proxy(&mlp, &need_init_cmd) < 0) exit(EXIT_FAILURE); } #endif /* * choose the TPM version early so that getting/setting * buffer size works. */ if (TPMLIB_ChooseTPMVersion(mlp.tpmversion) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not choose TPM version.\n"); exit(EXIT_FAILURE); } if (printcapabilities) { ret = capabilities_print_json(false); exit(ret ? EXIT_FAILURE : EXIT_SUCCESS); } SWTPM_NVRAM_Set_TPMVersion(mlp.tpmversion); if (mlp.fd < 0) { logprintf(STDERR_FILENO, "Error: Missing character device or file descriptor\n"); exit(EXIT_FAILURE); } else if (mlp.fd < 3) { /* no std{in,out,err} */ logprintf(STDERR_FILENO, "Error: Cannot accept file descriptors with values 0, 1, or 2\n"); exit(EXIT_FAILURE); } if (handle_ctrlchannel_options(ctrlchdata, &mlp.cc) < 0) { goto exit_failure; } /* change process ownership before accessing files */ if (runas) { if (change_process_owner(runas) < 0) goto exit_failure; } if (handle_log_options(logdata) < 0 || handle_key_options(keydata) < 0 || handle_migration_key_options(migkeydata) < 0 || handle_pid_options(piddata) < 0 || handle_tpmstate_options(tpmstatedata) < 0 || handle_seccomp_options(seccompdata, &seccomp_action) < 0 || handle_flags_options(flagsdata, &need_init_cmd, &mlp.startupType) < 0) { goto exit_failure; } if (daemonize) { #if defined __APPLE__ if (0 != osx_daemon(1, 0)) { #else if (0 != daemon(1, 0)) { #endif logprintf(STDERR_FILENO, "Error: Could not daemonize.\n"); goto exit_failure; } } if (pidfile_write(getpid()) < 0) { goto exit_failure; } setvbuf(stdout, 0, _IONBF, 0); /* output may be going through pipe */ #ifdef DEBUG /* initialization */ start_time = time(NULL); #endif TPM_DEBUG("main: Initializing TPM at %s", ctime(&start_time)); tpmlib_debug_libtpms_parameters(mlp.tpmversion); if ((rc = tpmlib_register_callbacks(&callbacks))) goto error_no_tpm; if (!need_init_cmd) { if ((rc = tpmlib_start(0, mlp.tpmversion))) goto error_no_tpm; tpm_running = true; } if (install_sighandlers(notify_fd, sigterm_handler) < 0) goto error_no_sighandlers; if (create_seccomp_profile(false, seccomp_action) < 0) goto error_seccomp_profile; mlp.flags |= MAIN_LOOP_FLAG_USE_FD | MAIN_LOOP_FLAG_KEEP_CONNECTION | \ MAIN_LOOP_FLAG_END_ON_HUP; rc = mainLoop(&mlp, notify_fd[0]); error_seccomp_profile: uninstall_sighandlers(); error_no_sighandlers: TPMLIB_Terminate(); error_no_tpm: close(notify_fd[0]); notify_fd[0] = -1; close(notify_fd[1]); notify_fd[1] = -1; swtpm_cleanup(mlp.cc); /* Fatal initialization errors cause the program to abort */ if (rc == 0) { exit(EXIT_SUCCESS); } else { TPM_DEBUG("main: TPM initialization failure %08x, exiting\n", rc); exit(EXIT_FAILURE); } exit_failure: swtpm_cleanup(mlp.cc); exit(EXIT_FAILURE); } swtpm-0.6.3/src/swtpm/swtpm_debug.c000066400000000000000000000107061421141172300173170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Debug Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_debug.c 4179 2010-11-10 20:10:24Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #define _GNU_SOURCE #include #include #include #include #include #include "swtpm_debug.h" #include "logging.h" /* * SWTPM_AppendPrintf() print and append to buffer * * @buffer: pointer to existing buffer or pointer to NULL to start a new buffer * @fmt: typical printf fmt * @...: varagr printf parameters * */ static int SWTPM_AppendPrintf(char **buffer, const char *fmt, ...) { va_list ap; int n, len = 0; char *dest = NULL, *nbuffer; va_start(ap, fmt); n = vasprintf(&dest, fmt, ap); va_end(ap); if (n < 0) return n; if (*buffer) len = strlen(*buffer); nbuffer = malloc(len + n + 1); if (!nbuffer) { free(dest); return -1; } if (*buffer) memcpy(nbuffer, *buffer, len); memcpy(&nbuffer[len], dest, n); nbuffer[len + n] = 0; free(dest); free(*buffer); *buffer = nbuffer; return len + n; } /* SWTPM_PrintAll() prints 'string', the length, and then the entire byte array */ void SWTPM_PrintAll(const char *string, const char *indentation, const unsigned char* buff, uint32_t length) { uint32_t i; int indent; char *linebuffer = NULL; indent = log_check_string(string); if (indent < 0) return; if (buff != NULL) { logprintf(STDERR_FILENO, "%s length %u\n", string, length); SWTPM_AppendPrintf(&linebuffer, "%s", indentation); for (i = 0 ; i < length ; i++) { if (i && !( i % 16 )) { SWTPM_AppendPrintf(&linebuffer, "\n"); logprintfA(STDERR_FILENO, 0, linebuffer); free(linebuffer); linebuffer = NULL; SWTPM_AppendPrintf(&linebuffer, "%s", indentation); } SWTPM_AppendPrintf(&linebuffer, "%.2X ", buff[i]); } SWTPM_AppendPrintf(&linebuffer, "\n"); logprintf(STDERR_FILENO, "%s", linebuffer); free(linebuffer); } else { logprintf(STDERR_FILENO, "%s null\n", string); } return; } swtpm-0.6.3/src/swtpm/swtpm_debug.h000066400000000000000000000037501421141172300173250ustar00rootroot00000000000000/* * swtpm_debug.h * * Author: Stefan Berger stefanb@us.ibm.com * * * (c) Copyright IBM Corporation 2014. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_DEBUG_H_ #define _SWTPM_DEBUG_H_ # include # ifdef DEBUG # include "logging.h" # define TPM_DEBUG(args...) logprintf(STDOUT_FILENO, ## args) # else # define TPM_DEBUG(...) # endif /* DEBUG */ void SWTPM_PrintAll(const char *string, const char *indent, const unsigned char* buff, uint32_t length); #endif /* _SWTPM_DEBUG_H_ */ swtpm-0.6.3/src/swtpm/swtpm_io.c000066400000000000000000000200771421141172300166420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Host IO */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_io.c 4564 2011-04-13 19:33:38Z stefanb $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010, 2019 */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* These are platform specific. This version uses a TCP/IP socket interface. Environment variables are: TPM_PORT - the client and server socket port number */ #include #include #include #include #include #include #include #include #include /* BSD: sockaddr_in */ #include /* BSD: accept() */ #include /* BSD: select() */ #include #include #include #include #include "logging.h" #include "swtpm_debug.h" #include "swtpm_io.h" #include "tpmlib.h" #include "utils.h" /* global variables */ /* platform dependent */ static int sock_fd = -1; /* SWTPM_IO_Read() reads a TPM command packet from the host Puts the result in 'buffer' up to 'bufferSize' bytes. On success, the number of bytes in the buffer is equal to 'bufferLength' bytes This function is intended to be platform independent. */ TPM_RESULT SWTPM_IO_Read(TPM_CONNECTION_FD *connection_fd, /* read/write file descriptor */ unsigned char *buffer, /* output: command stream */ uint32_t *bufferLength, /* output: command stream length */ size_t bufferSize) /* input: max size of output buffer */ { ssize_t n; size_t offset = 0; if (connection_fd->fd < 0) { TPM_DEBUG("SWTPM_IO_Read: Passed file descriptor is invalid\n"); return TPM_IOERROR; } while (true) { n = read(connection_fd->fd, &buffer[offset], bufferSize - offset); if (n < 0 && errno == EINTR) continue; if (n > 0) { offset += n; if (offset < sizeof(struct tpm_req_header)) continue; break; } else { return TPM_IOERROR; } } *bufferLength = offset; SWTPM_PrintAll(" SWTPM_IO_Read:", " ", buffer, *bufferLength); return 0; } /* SWTPM_IO_SetSocketFD tells the IO layer that it's not necessary to open a server socket. */ TPM_RESULT SWTPM_IO_SetSocketFD(int fd) { sock_fd = fd; return 0; } int SWTPM_IO_GetSocketFD(void) { return sock_fd; } /* SWTPM_IO_Init initializes the TPM to host interface. This is the Unix platform dependent socket version. */ TPM_RESULT SWTPM_IO_Init(void) { TPM_DEBUG(" SWTPM_IO_Init:\n"); return 0; } /* SWTPM_IO_Connect() establishes a connection between the TPM server and the host client This is the Unix platform dependent socket version. */ TPM_RESULT SWTPM_IO_Connect(TPM_CONNECTION_FD *connection_fd, /* read/write file descriptor */ int notify_fd) { TPM_RESULT rc = 0; socklen_t cli_len; struct sockaddr_in cli_addr; /* Internet version of sockaddr */ int max_fd = -1; fd_set readfds; int n; while (rc == 0) { FD_ZERO(&readfds); FD_SET(sock_fd, &readfds); max_fd = sock_fd; FD_SET(notify_fd, &readfds); max_fd = (notify_fd > max_fd) ? notify_fd : max_fd; TPM_DEBUG("SWTPM_IO_Connect: Waiting for connections\n"); n = select(max_fd + 1, &readfds, NULL, NULL, NULL); if (n > 0 && FD_ISSET(notify_fd, &readfds)) { rc = TPM_IOERROR; break; } if (n > 0 && FD_ISSET(sock_fd, &readfds)) { cli_len = sizeof(cli_addr); /* block until connection from client */ TPM_DEBUG("\n SWTPM_IO_Connect: Accepting connection ...\n"); connection_fd->fd = accept(sock_fd, (struct sockaddr *)&cli_addr, &cli_len); if (connection_fd->fd < 0) { logprintf(STDERR_FILENO, "SWTPM_IO_Connect: Error, accept() %d %s\n", errno, strerror(errno)); rc = TPM_IOERROR; } break; } } return rc; } /* SWTPM_IO_Write() writes 'buffer_length' bytes to the host. This is the Unix platform dependent socket version. */ TPM_RESULT SWTPM_IO_Write(TPM_CONNECTION_FD *connection_fd, /* read/write file descriptor */ const struct iovec *iovec, int iovcnt) { ssize_t nwritten = 0; size_t totlen = 0; int i; SWTPM_PrintAll(" SWTPM_IO_Write:", " ", iovec[1].iov_base, iovec[1].iov_len); /* test that connection is open to write */ if (connection_fd->fd < 0) { logprintf(STDERR_FILENO, "SWTPM_IO_Write: Error, connection not open, fd %d\n", connection_fd->fd); return TPM_IOERROR; } for (i = 0; i < iovcnt; i++) totlen += iovec[i].iov_len; nwritten = writev_full(connection_fd->fd, iovec, iovcnt); if (nwritten < 0) { logprintf(STDERR_FILENO, "SWTPM_IO_Write: Error, writev() %d %s\n", errno, strerror(errno)); return TPM_IOERROR; } if ((size_t)nwritten < totlen) { logprintf(STDERR_FILENO, "SWTPM_IO_Write: Failed to write all bytes %zu != %zu\n", nwritten, totlen); return TPM_IOERROR; } return 0; } /* SWTPM_IO_Disconnect() breaks the connection between the TPM server and the host client This is the Unix platform dependent socket version. */ TPM_RESULT SWTPM_IO_Disconnect(TPM_CONNECTION_FD *connection_fd) { /* close the connection to the client */ if (connection_fd->fd >= 0) { close(connection_fd->fd); connection_fd->fd = -1; /* mark the connection closed */ } return 0; } swtpm-0.6.3/src/swtpm/swtpm_io.h000066400000000000000000000066131421141172300166470ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Host IO */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_io.h 4211 2010-11-22 21:07:24Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef _SWTPM_IO_H_ #define _SWTPM_IO_H_ typedef struct TPM_CONNECTION_FD { int fd; /* for socket, just an int */ } TPM_CONNECTION_FD; TPM_RESULT SWTPM_IO_Init(void); TPM_RESULT SWTPM_IO_Connect(TPM_CONNECTION_FD *connection_fd, int notify_fd); TPM_RESULT SWTPM_IO_Read(TPM_CONNECTION_FD *connection_fd, unsigned char *buffer, uint32_t *paramSize, size_t buffer_size); TPM_RESULT SWTPM_IO_Write(TPM_CONNECTION_FD *connection_fd, const struct iovec *iovec, int iovcnt); TPM_RESULT SWTPM_IO_Disconnect(TPM_CONNECTION_FD *connection_fd); TPM_RESULT SWTPM_IO_SetSocketFD(int fd); int SWTPM_IO_GetSocketFD(void); #define LOAD32(buffer,offset) ( ntohl(*(uint32_t *)&(buffer)[(offset)]) ) #define LOAD16(buffer,offset) ( ntohs(*(uint16_t *)&(buffer)[(offset)]) ) #define LOAD8(buffer,offset) ( (*(uint8_t *)&(buffer)[(offset)]) ) #endif /* _SWTPM_IO_H_ */ swtpm-0.6.3/src/swtpm/swtpm_nvfile.c000066400000000000000000001426621421141172300175230ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM File Abstraction Layer */ /* Written by Ken Goldman */ /* Adapted to SWTPM by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2006, 2010, 2014, 2015. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* This module abstracts out all NVRAM read and write operations. This implementation uses standard, portable C files. The basic high level abstractions are: SWTPM_NVRAM_LoadData(); SWTPM_NVRAM_StoreData(); SWTPM_NVRAM_DeleteName(); They take a 'name' that is mapped to a rooted file name. */ #include "config.h" #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__OpenBSD__) # define OPENSSL_OLD_API #else #if OPENSSL_VERSION_NUMBER < 0x10100000 #define OPENSSL_OLD_API #endif #endif #include "swtpm.h" #include "swtpm_aes.h" #include "swtpm_debug.h" #include "swtpm_nvfile.h" #include "key.h" #include "logging.h" #include "tpmstate.h" #include "tpmlib.h" #include "tlv.h" #include "utils.h" /* local structures */ typedef struct { uint8_t version; uint8_t min_version; /* min. required version */ uint16_t hdrsize; uint16_t flags; uint32_t totlen; /* length of the header and following data */ } __attribute__((packed)) blobheader; #define BLOB_HEADER_VERSION 2 /* flags for blobheader */ #define BLOB_FLAG_ENCRYPTED 0x01 #define BLOB_FLAG_MIGRATION_ENCRYPTED 0x02 /* encrypted with migration key */ #define BLOB_FLAG_MIGRATION_DATA 0x04 /* migration data are available */ #define BLOB_FLAG_ENCRYPTED_256BIT_KEY 0x08 /* 256 bit file key was used */ #define BLOB_FLAG_MIGRATION_256BIT_KEY 0x10 /* 256 bit migration key was used */ typedef struct { enum encryption_mode data_encmode; TPM_SYMMETRIC_KEY_DATA symkey; } encryptionkey ; static encryptionkey filekey = { .symkey = { .userKeyLength = 0, }, }; static encryptionkey migrationkey = { .symkey = { .userKeyLength = 0, }, }; static uint32_t g_ivec_length; static unsigned char *g_ivec; /* local prototypes */ static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, size_t bufsize, uint32_t tpm_number, const char *name, bool is_tempfile); static TPM_RESULT SWTPM_NVRAM_EncryptData(const encryptionkey *key, tlv_data *td, size_t *td_len, uint16_t tag_encrypted_data, const unsigned char *decrypt_data, uint32_t decrypt_length, uint16_t tag_ivec); static TPM_RESULT SWTPM_NVRAM_GetDecryptedData(const encryptionkey *key, unsigned char **decrypt_data, uint32_t *decrypt_length, const unsigned char *encrypt_data, uint32_t encrypt_length, uint16_t tag_decryped_data, uint16_t tag_data, uint8_t hdrversion, uint16_t tag_ivec, uint16_t hdrflags, uint16_t flag_256bitkey); static TPM_RESULT SWTPM_NVRAM_PrependHeader(unsigned char **data, uint32_t *length, uint16_t flags); static TPM_RESULT SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length, uint32_t *dataoffset, uint16_t *hdrflags, uint8_t *hdrversion, bool quiet); /* A file name in NVRAM is composed of 3 parts: 1 - 'state_directory' is the rooted path to the TPM state home directory 2 = 'tpm_number' is the TPM instance, 00 for a single TPM 2 - the file name For the IBM cryptographic coprocessor version, the root path is hard coded. For the Linux and Windows versions, the path comes from an environment variable. This variable is used once in TPM_NVRAM_Init(). One root path is used for all virtual TPM's, so it can be a static variable. */ static int lockfile_fd = -1; char state_directory[FILENAME_MAX]; static TPMLIB_TPMVersion tpmversion = TPMLIB_TPM_VERSION_1_2; /* * SWTPM_NVRAM_Set_TPMVersion() - set the version of the TPM being used */ void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version) { tpmversion = version; } static TPM_RESULT SWTPM_NVRAM_Lock_Lockfile(const char *directory, int *fd) { TPM_RESULT rc = 0; char *lockfile = NULL; struct flock flock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0, }; if (asprintf(&lockfile, "%s/.lock", directory) < 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_Lock_Lockfile: Could not asprintf lock filename\n"); return TPM_FAIL; } *fd = open(lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, 0660); if (*fd < 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_Lock_Lockfile: Could not open lockfile: %s\n", strerror(errno)); rc = TPM_FAIL; goto exit; } if (fcntl(*fd, F_SETLK, &flock) < 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_Lock_Lockfile: Could not lock access to lockfile: %s\n", strerror(errno)); rc = TPM_FAIL; close(*fd); *fd = -1; } exit: free(lockfile); return rc; } /* TPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization. This function sets some static variables that are used by all TPM's. */ TPM_RESULT SWTPM_NVRAM_Init(void) { TPM_RESULT rc = 0; const char *tpm_state_path; size_t length; TPM_DEBUG(" SWTPM_NVRAM_Init:\n"); /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */ if (rc == 0) { tpm_state_path = tpmstate_get_dir(); if (tpm_state_path == NULL) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_Init: Error (fatal), TPM_PATH environment " "variable not set\n"); rc = TPM_FAIL; } } /* check that the directory name plus a file name will not overflow FILENAME_MAX */ if (rc == 0) { length = strlen(tpm_state_path); if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_Init: Error (fatal), TPM state path name " "%s too large\n", tpm_state_path); rc = TPM_FAIL; } } if (rc == 0) { strcpy(state_directory, tpm_state_path); TPM_DEBUG("TPM_NVRAM_Init: Rooted state path %s\n", state_directory); } if (rc == 0 && lockfile_fd < 0) rc = SWTPM_NVRAM_Lock_Lockfile(state_directory, &lockfile_fd); return rc; } void SWTPM_NVRAM_Shutdown(void) { memset(&filekey, 0, sizeof(filekey)); memset(&migrationkey, 0, sizeof(migrationkey)); } /* Load 'data' of 'length' from the 'name'. 'data' must be freed after use. Returns 0 on success. TPM_RETRY and NULL,0 on non-existent file (non-fatal, first time start up) TPM_FAIL on failure to load (fatal), since it should never occur */ TPM_RESULT SWTPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ uint32_t *length, uint32_t tpm_number, const char *name) { TPM_RESULT rc = 0; size_t src; int irc; int fd = -1; char filename[FILENAME_MAX]; /* rooted file name from name */ unsigned char *decrypt_data = NULL; uint32_t decrypt_length; uint32_t dataoffset = 0; uint8_t hdrversion = 0; uint16_t hdrflags; struct stat statbuf; TPM_DEBUG(" SWTPM_NVRAM_LoadData: From file %s\n", name); *data = NULL; *length = 0; /* open the file */ if (rc == 0) { /* map name to the rooted filename */ rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name, false); } if (rc == 0) { TPM_DEBUG(" SWTPM_NVRAM_LoadData: Opening file %s\n", filename); fd = open(filename, O_RDONLY); /* closed @1 */ if (fd < 0) { /* if failure, determine cause */ if (errno == ENOENT) { TPM_DEBUG("SWTPM_NVRAM_LoadData: No such file %s\n", filename); rc = TPM_RETRY; /* first time start up */ } else { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error (fatal) opening " "%s for read, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } } if (rc == 0) { if (fchmod(fd, tpmstate_get_mode()) < 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Could not fchmod %s : %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } /* determine the file length */ if (rc == 0) { irc = fstat(fd, &statbuf); if (irc == -1L) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error (fatal) fstat'ing %s, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } if (rc == 0) { *length = statbuf.st_size; /* save the length */ } /* allocate a buffer for the actual data */ if ((rc == 0) && *length != 0) { TPM_DEBUG(" SWTPM_NVRAM_LoadData: Reading %u bytes of data\n", *length); *data = malloc(*length); if (!*data) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error (fatal) allocating %u " "bytes\n", *length); rc = TPM_FAIL; } } /* read the contents of the file into the data buffer */ if ((rc == 0) && *length != 0) { src = read(fd, *data, *length); if (src != *length) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error (fatal), data read of %u " "only read %lu\n", *length, (unsigned long)src); rc = TPM_FAIL; } } /* close the file */ if (fd >= 0) { TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closing file %s\n", filename); irc = close(fd); /* @1 */ if (irc != 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error (fatal) closing file %s\n", filename); rc = TPM_FAIL; } else { TPM_DEBUG(" SWTPM_NVRAM_LoadData: Closed file %s\n", filename); } } if (rc == 0) { /* this function needs to return the plain data -- no tlv headers */ /* try to get a header from it -- old files may not have one */ irc = SWTPM_NVRAM_CheckHeader(*data, *length, &dataoffset, &hdrflags, &hdrversion, true); /* valid header -- this one can only be version 2 or later */ if (irc) { hdrversion = 1; /* no header -- payload was written like vers. 1 */ hdrflags = 0; } rc = SWTPM_NVRAM_GetDecryptedData(&filekey, &decrypt_data, &decrypt_length, *data + dataoffset, *length - dataoffset, TAG_ENCRYPTED_DATA, TAG_DATA, hdrversion, TAG_IVEC_ENCRYPTED_DATA, hdrflags, BLOB_FLAG_ENCRYPTED_256BIT_KEY); TPM_DEBUG(" SWTPM_NVRAM_LoadData: SWTPM_NVRAM_GetDecryptedData rc = %d\n", rc); if (rc != 0) logprintf(STDERR_FILENO, "SWTPM_NVRAM_LoadData: Error from SWTPM_NVRAM_GetDecryptedData " "rc = %d\n", rc); if (rc == 0) { TPM_DEBUG(" SWTPM_NVRAM_LoadData: Decrypted %u bytes of " "data to %u bytes.\n", *length, decrypt_length); free(*data); *data = decrypt_data; *length = decrypt_length; } } if (rc != 0) { free(*data); *data = NULL; } return rc; } /* SWTPM_NVRAM_StoreData stores 'data' of 'length' to the rooted 'filename' Returns 0 on success TPM_FAIL for other fatal errors */ static TPM_RESULT SWTPM_NVRAM_StoreData_Intern(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name, TPM_BOOL encrypt /* encrypt if key is set */) { TPM_RESULT rc = 0; uint32_t lrc; int irc; int fd = -1; char tmpfile[FILENAME_MAX]; /* rooted temporary file */ char filename[FILENAME_MAX]; /* rooted file name from name */ unsigned char *filedata = NULL; uint32_t filedata_length = 0; tlv_data td[3]; size_t td_len = 0; uint16_t flags = 0; TPM_DEBUG(" SWTPM_NVRAM_StoreData: To name %s\n", name); if (rc == 0) { /* map name to the rooted filename */ rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name, false); } if (rc == 0) { /* map name to the rooted temporary file */ rc = SWTPM_NVRAM_GetFilenameForName(tmpfile, sizeof(tmpfile), tpm_number, name, true); } if (rc == 0) { /* open the file */ TPM_DEBUG(" SWTPM_NVRAM_StoreData: Opening file %s\n", tmpfile); fd = open(tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, tpmstate_get_mode()); /* closed @1 */ if (fd < 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_StoreData: Error (fatal) opening %s for " "write failed, %s\n", tmpfile, strerror(errno)); rc = TPM_FAIL; } } if (rc == 0) { if (encrypt && SWTPM_NVRAM_Has_FileKey()) { td_len = 3; rc = SWTPM_NVRAM_EncryptData(&filekey, &td[0], &td_len, TAG_ENCRYPTED_DATA, data, length, TAG_IVEC_ENCRYPTED_DATA); if (rc) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_EncryptData failed: 0x%02x\n", rc); } else { TPM_DEBUG(" SWTPM_NVRAM_StoreData: Encrypted %u bytes before " "write, will write %u bytes\n", length, td[0].tlv.length); } flags |= BLOB_FLAG_ENCRYPTED; if (SWTPM_NVRAM_FileKey_Size() == SWTPM_AES256_BLOCK_SIZE) flags |= BLOB_FLAG_ENCRYPTED_256BIT_KEY; } else { td_len = 1; td[0] = TLV_DATA_CONST(TAG_DATA, length, data); } } if (rc == 0) rc = tlv_data_append(&filedata, &filedata_length, td, td_len); if (rc == 0) rc = SWTPM_NVRAM_PrependHeader(&filedata, &filedata_length, flags); /* write the data to the file */ if (rc == 0) { TPM_DEBUG(" SWTPM_NVRAM_StoreData: Writing %u bytes of data\n", length); lrc = write_full(fd, filedata, filedata_length); if (lrc != filedata_length) { logprintf(STDERR_FILENO, "TPM_NVRAM_StoreData: Error (fatal), data write " "of %u only wrote %u\n", filedata_length, lrc); rc = TPM_FAIL; } } if (fd >= 0) { TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closing file %s\n", tmpfile); irc = close(fd); /* @1 */ if (irc != 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_StoreData: Error (fatal) closing file\n"); rc = TPM_FAIL; } else { TPM_DEBUG(" SWTPM_NVRAM_StoreData: Closed file %s\n", tmpfile); } } if (rc == 0 && fd >= 0) { irc = rename(tmpfile, filename); if (irc != 0) { logprintf(STDERR_FILENO, "SWTPM_NVRAM_StoreData: Error (fatal) renaming file: %s\n", strerror(errno)); rc = TPM_FAIL; } else { TPM_DEBUG(" SWTPM_NVRAM_StoreData: Renamed file to %s\n", filename); } } if (rc != 0 && fd >= 0) { unlink(tmpfile); } tlv_data_free(td, td_len); free(filedata); TPM_DEBUG(" SWTPM_NVRAM_StoreData: rc=%d\n", rc); return rc; } TPM_RESULT SWTPM_NVRAM_StoreData(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name) { return SWTPM_NVRAM_StoreData_Intern(data, length, tpm_number, name, TRUE); } /* SWTPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name. The filename is of the form: state_directory/tpm_number.name A temporary filename used to write to may be created. It shold be rename()'d to the non-temporary filename. */ static TPM_RESULT SWTPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ size_t bufsize, uint32_t tpm_number, const char *name, /* input: abstract name */ bool is_tempfile) /* input: is temporary file? */ { TPM_RESULT res = TPM_SUCCESS; int n; const char *suffix = ""; TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: For name %s\n", name); switch (tpmversion) { case TPMLIB_TPM_VERSION_1_2: break; case TPMLIB_TPM_VERSION_2: suffix = "2"; break; } if (is_tempfile) { n = snprintf(filename, bufsize, "%s/TMP%s-%02lx.%s", state_directory, suffix, (unsigned long)tpm_number, name); } else { n = snprintf(filename, bufsize, "%s/tpm%s-%02lx.%s", state_directory, suffix, (unsigned long)tpm_number, name); } if ((size_t)n > bufsize) { res = TPM_FAIL; } TPM_DEBUG(" SWTPM_NVRAM_GetFilenameForName: File name %s\n", filename); return res; } /* TPM_NVRAM_DeleteName() deletes the 'name' from NVRAM Returns: 0 on success, or if the file does not exist and mustExist is FALSE TPM_FAIL if the file could not be removed, since this should never occur and there is no recovery NOTE: Not portable code, but supported by Linux and Windows */ TPM_RESULT SWTPM_NVRAM_DeleteName(uint32_t tpm_number, const char *name, TPM_BOOL mustExist) { TPM_RESULT rc = 0; int irc; char filename[FILENAME_MAX]; /* rooted file name from name */ TPM_DEBUG(" SWTPM_NVRAM_DeleteName: Name %s\n", name); /* map name to the rooted filename */ rc = SWTPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name, false); if (rc == 0) { irc = remove(filename); if ((irc != 0) && /* if the remove failed */ (mustExist || /* if any error is a failure, or */ (errno != ENOENT))) { /* if error other than no such file */ logprintf(STDERR_FILENO, "SWTPM_NVRAM_DeleteName: Error, (fatal) file " "remove failed, errno %d\n", errno); rc = TPM_FAIL; } } return rc; } TPM_RESULT SWTPM_NVRAM_Store_Volatile(void) { TPM_RESULT rc = 0; char *name = TPM_VOLATILESTATE_NAME; uint32_t tpm_number = 0; unsigned char *buffer = NULL; uint32_t buflen; TPM_DEBUG(" SWTPM_Store_Volatile: Name %s\n", name); if (rc == 0) { rc = TPMLIB_VolatileAll_Store(&buffer, &buflen); } if (rc == 0) { /* map name to the rooted filename */ rc = SWTPM_NVRAM_StoreData(buffer, buflen, tpm_number, name); } free(buffer); return rc; } static TPM_RESULT SWTPM_NVRAM_KeyParamCheck(uint32_t keylen, enum encryption_mode encmode) { TPM_RESULT rc = 0; if (keylen != SWTPM_AES128_BLOCK_SIZE && keylen != SWTPM_AES256_BLOCK_SIZE) { rc = TPM_BAD_KEY_PROPERTY; } switch (encmode) { case ENCRYPTION_MODE_AES_CBC: break; case ENCRYPTION_MODE_UNKNOWN: rc = TPM_BAD_MODE; } return rc; } size_t SWTPM_NVRAM_FileKey_Size(void) { return filekey.symkey.userKeyLength; } TPM_RESULT SWTPM_NVRAM_Set_FileKey(const unsigned char *key, uint32_t keylen, enum encryption_mode encmode) { TPM_RESULT rc; rc = SWTPM_NVRAM_KeyParamCheck(keylen, encmode); if (rc == 0) { memcpy(filekey.symkey.userKey, key, keylen); filekey.symkey.userKeyLength = keylen; filekey.data_encmode = encmode; } return rc; } size_t SWTPM_NVRAM_MigrationKey_Size(void) { return migrationkey.symkey.userKeyLength; } TPM_RESULT SWTPM_NVRAM_Set_MigrationKey(const unsigned char *key, uint32_t keylen, enum encryption_mode encmode) { TPM_RESULT rc; rc = SWTPM_NVRAM_KeyParamCheck(keylen, encmode); if (rc == 0) { memcpy(migrationkey.symkey.userKey, key, keylen); migrationkey.symkey.userKeyLength = keylen; migrationkey.data_encmode = encmode; } return rc; } static int SWTPM_HMAC(unsigned char *md, unsigned int *md_len, const void *key, int key_len, const unsigned char *in, uint32_t in_length, const unsigned char *ivec, uint32_t ivec_length) { int ret = 0; #if defined OPENSSL_OLD_API HMAC_CTX sctx, *ctx = &sctx; HMAC_CTX_init(ctx); #else HMAC_CTX *ctx = HMAC_CTX_new(); if (!ctx) return 0; #endif if (!HMAC_Init_ex(ctx, key, key_len, EVP_sha256(), NULL) || !HMAC_Update(ctx, in, in_length)) goto err; if (ivec && !HMAC_Update(ctx, ivec, ivec_length)) goto err; if (!HMAC_Final(ctx, md, md_len)) goto err; ret = 1; err: #if defined OPENSSL_OLD_API HMAC_CTX_cleanup(ctx); #else HMAC_CTX_free(ctx); #endif return ret; } /* * SWTPM_RollAndSetGlobalIvec: Create an IV for the AES CBC algorithm to use * Create it with a random number every time. * and leave the pointer to the data in @td. * * @td: pointer to tlv_data to get pointer to the random data * @tag_ivec: tag for the IV tlv header * @ivec_length: number of bytes needed for the ivec */ static TPM_RESULT SWTPM_RollAndSetGlobalIvec(tlv_data *td, uint16_t tag_ivec, uint32_t ivec_length) { unsigned char data[16]; /* do not initialize */ unsigned char hashbuf[SHA256_DIGEST_LENGTH]; void *p; if (g_ivec_length < ivec_length) { p = realloc(g_ivec, ivec_length); if (!p) { *td = TLV_DATA_CONST(tag_ivec, 0, NULL); logprintf(STDOUT_FILENO, "Could not allocate %u bytes.\n", ivec_length); return TPM_FAIL; } g_ivec = p; g_ivec_length = ivec_length; } if (RAND_bytes(g_ivec, g_ivec_length) != 1) { /* random data from stack to the rescue */ SHA256(g_ivec, g_ivec_length, hashbuf); SHA256(data, sizeof(data), hashbuf); memcpy(g_ivec, hashbuf, g_ivec_length < sizeof(hashbuf) ? g_ivec_length : sizeof(hashbuf)); } *td = TLV_DATA_CONST(tag_ivec, g_ivec_length, g_ivec); return 0; } /* * SWTPM_GetIvec: Get the encryption IV from the data stream. If none is * found a NULL pointer is set in *ivec, otherwise a pointer * to the beginning of the IV and its length are returned. */ static void SWTPM_GetIvec(const unsigned char *data, uint32_t length, const unsigned char **ivec, uint32_t *ivec_length, uint16_t tag) { tlv_data td; if (!tlv_data_find_tag(data, length, tag, &td)) { *ivec = NULL; } else { *ivec = td.u.const_ptr; *ivec_length = td.tlv.length; } } /* * SWTPM_CalcHMAC * * @in: input buffer to calculate HMAC on * @in_length: length of input buffer * @td: pointer to a tlv_data structure to receive the result with the * tag, length, and pointer to an allocated buffer holding the HMAC * @tpm_symmetric_key_token: symmetric key * @ivec: the IV for AES CBC * @ivec_length: the length of the IV * * Calculate an HMAC on the input buffer with payload and create an output * buffer with the HMAC */ static TPM_RESULT SWTPM_CalcHMAC(const unsigned char *in, uint32_t in_length, tlv_data *td, const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, const unsigned char *ivec, uint32_t ivec_length) { TPM_RESULT rc = 0; unsigned int md_len; unsigned char md[EVP_MAX_MD_SIZE]; unsigned char *buffer = NULL; if (!SWTPM_HMAC(md, &md_len, tpm_symmetric_key_token->userKey, tpm_symmetric_key_token->userKeyLength, in, in_length, ivec, ivec_length)) { logprintf(STDOUT_FILENO, "HMAC calculation failed.\n"); return TPM_FAIL; } buffer = malloc(md_len); if (buffer) { *td = TLV_DATA(TAG_HMAC, md_len, buffer); memcpy(buffer, md, md_len); } else { logprintf(STDOUT_FILENO, "Could not allocate %u bytes.\n", md_len); rc = TPM_FAIL; } return rc; } /* * SWTPM_CheckHMAC: * * @hmac: tlv_data with pointer to hmac bytes * @encrypted_data: tlv_data with pointer to encrypted data bytes * @tpm_symmetric_key_token: symmetric key * @ivec: the IV for AES CBC * @ivec_length: the length of the IV * * Verify the HMAC given the expected @hmac and the @tpm_symmetric_key_token * to calculate the HMAC over the @encrypted_data. */ static TPM_RESULT SWTPM_CheckHMAC(tlv_data *hmac, tlv_data *encrypted_data, const TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_token, const unsigned char *ivec, uint32_t ivec_length) { const unsigned char *data; uint32_t data_length; unsigned int md_len; unsigned char md[EVP_MAX_MD_SIZE]; md_len = EVP_MD_size(EVP_sha256()); if (md_len > hmac->tlv.length) { logprintf(STDOUT_FILENO, "Insufficient bytes for CheckHMAC()\n"); return TPM_FAIL; } data = encrypted_data->u.ptr; data_length = encrypted_data->tlv.length; if (!SWTPM_HMAC(md, &md_len, tpm_symmetric_key_token->userKey, tpm_symmetric_key_token->userKeyLength, data, data_length, ivec, ivec_length)) { logprintf(STDOUT_FILENO, "HMAC() call failed.\n"); return TPM_FAIL; } if (memcmp(hmac->u.ptr, md, md_len)) { logprintf(STDOUT_FILENO, "Verification of HMAC failed. " "Data integrity is compromised\n"); /* TPM_DECRYPT_ERROR indicates (to libtpms) that something exists but we have the wrong key. */ return TPM_DECRYPT_ERROR; } return TPM_SUCCESS; } /* * SWTPM_CheckHash: * * @in: input buffer * @in_length: input buffer length * @out: output buffer * @out_length: output buffer length */ static TPM_RESULT SWTPM_CheckHash(const unsigned char *in, uint32_t in_length, unsigned char **out, uint32_t *out_length) { TPM_RESULT rc = 0; unsigned char *dest = NULL; unsigned char hashbuf[SHA256_DIGEST_LENGTH]; const unsigned char *data = &in[sizeof(hashbuf)]; uint32_t data_length = in_length - sizeof(hashbuf); /* hash the data */ SHA256(data, data_length, hashbuf); if (memcmp(in, hashbuf, sizeof(hashbuf))) { logprintf(STDOUT_FILENO, "Verification of hash failed. " "Data integrity is compromised\n"); rc = TPM_FAIL; } if (rc == 0) { dest = malloc(data_length); if (dest) { *out = dest; *out_length = data_length; memcpy(dest, data, data_length); } else { logprintf(STDOUT_FILENO, "Could not allocated %u bytes.\n", data_length); rc = TPM_FAIL; } } return rc; } static TPM_RESULT SWTPM_NVRAM_EncryptData(const encryptionkey *key, struct tlv_data *td, /* must provide 2 array members */ size_t *td_len, uint16_t tag_encrypted_data, const unsigned char *data, uint32_t length, uint16_t tag_ivec) { TPM_RESULT rc = 0; TPM_RESULT irc; unsigned char *tmp_data = NULL; uint32_t tmp_length = 0; *td_len = 0; if (key->symkey.userKeyLength > 0) { switch (key->data_encmode) { case ENCRYPTION_MODE_UNKNOWN: rc = TPM_BAD_MODE; break; case ENCRYPTION_MODE_AES_CBC: irc = SWTPM_RollAndSetGlobalIvec(&td[2], tag_ivec, key->symkey.userKeyLength); rc = SWTPM_SymmetricKeyData_Encrypt(&tmp_data, &tmp_length, data, length, &key->symkey, td[2].u.const_ptr, td[2].tlv.length); if (rc) break; rc = SWTPM_CalcHMAC(tmp_data, tmp_length, &td[1], &key->symkey, td[2].u.const_ptr, td[2].tlv.length); if (rc == 0) { td[0] = TLV_DATA(tag_encrypted_data, tmp_length, tmp_data); /* in case we couldn't get an IV */ *td_len = (irc == 0) ? 3 : 2; tmp_data = NULL; } break; } } if (rc) tlv_data_free(td, *td_len); free(tmp_data); return rc; } static TPM_RESULT SWTPM_NVRAM_DecryptData(const encryptionkey *key, unsigned char **decrypt_data, uint32_t *decrypt_length, const unsigned char *data, uint32_t length, uint16_t tag_encrypted_data, uint8_t hdrversion, uint16_t tag_ivec, uint16_t hdrflags, uint16_t flag_256bitkey) { TPM_RESULT rc = 0; unsigned char *tmp_data = NULL; uint32_t tmp_length = 0; tlv_data td[2]; const unsigned char *ivec = NULL; uint32_t ivec_length = 0; size_t keylen; if (key->symkey.userKeyLength > 0) { switch (key->data_encmode) { case ENCRYPTION_MODE_UNKNOWN: rc = TPM_BAD_MODE; break; case ENCRYPTION_MODE_AES_CBC: switch (hdrversion) { case 1: rc = SWTPM_SymmetricKeyData_Decrypt(&tmp_data, &tmp_length, data, length, &key->symkey, NULL, 0); if (rc == 0) { rc = SWTPM_CheckHash(tmp_data, tmp_length, decrypt_data, decrypt_length); } break; case 2: keylen = (hdrflags & flag_256bitkey) ? SWTPM_AES256_BLOCK_SIZE : SWTPM_AES128_BLOCK_SIZE; if (keylen != key->symkey.userKeyLength) { logprintf(STDERR_FILENO, "Wrong decryption key. Need %zu bit key.\n", keylen * 8); rc = TPM_BAD_KEY_PROPERTY; break; } if (!tlv_data_find_tag(data, length, TAG_HMAC, &td[0]) || !tlv_data_find_tag(data, length, tag_encrypted_data, &td[1])) { logprintf(STDERR_FILENO, "Could not find HMAC or encrypted data (tag %u) " "in byte stream.\n", tag_encrypted_data); rc = TPM_FAIL; break; } /* get the IV, if there is one */ SWTPM_GetIvec(data, length, &ivec, &ivec_length, tag_ivec); rc = SWTPM_CheckHMAC(&td[0], &td[1], &key->symkey, ivec, ivec_length); if (rc == 0) { rc = SWTPM_SymmetricKeyData_Decrypt(decrypt_data, decrypt_length, td[1].u.const_ptr, td[1].tlv.length, &key->symkey, ivec, ivec_length); } break; default: rc = TPM_FAIL; } free(tmp_data); } } return rc; } static TPM_RESULT SWTPM_NVRAM_GetPlainData(unsigned char **plain, uint32_t *plain_length, const unsigned char *data, uint32_t length, uint16_t tag_data, uint8_t hdrversion) { TPM_RESULT rc = 0; tlv_data td[1]; switch (hdrversion) { case 1: *plain = malloc(length); if (*plain) { memcpy(*plain, data, length); *plain_length = length; } else { logprintf(STDERR_FILENO, "Could not allocate %u bytes.\n", length); rc = TPM_FAIL; } break; case 2: if (!tlv_data_find_tag(data, length, tag_data, &td[0])) { logprintf(STDERR_FILENO, "Could not find plain data in byte stream.\n"); rc = TPM_FAIL; break; } *plain = malloc(td->tlv.length); if (*plain) { memcpy(*plain, td->u.const_ptr, td->tlv.length); *plain_length = td->tlv.length; } else { logprintf(STDERR_FILENO, "Could not allocate %u bytes.\n", td->tlv.length); rc = TPM_FAIL; } break; } return rc; } /* * SWTPM_NVRAM_GetDecryptedData: Get the decrytped data either by just returning * the data if they were not encrypted or by * actually decrypting them if there is a key. * The plain data is returned, meaning any TLV * header has been removed. * @key: the encryption key, may be NULL * @decrypt_data: pointer to a pointer for the result * @decrypt_length: the length of the returned data * @data: input data * @length: length of the input data * @tag_encrypted_data: the tag the encrypted data is stored with * @tag_data: the tag the plain data is stored with * @hdrversion: the version found in the header that determines in what * format the data is stored; tag-length-value is the format * in v2 * @tag_ivec: the tag for finding the IV * @hdrflags: the flags from the header * @flag_256bitkey: the flag in the header to check whether we expect a * 256 bit key; different flag for migration and state key */ static TPM_RESULT SWTPM_NVRAM_GetDecryptedData(const encryptionkey *key, unsigned char **decrypt_data, uint32_t *decrypt_length, const unsigned char *data, uint32_t length, uint16_t tag_encrypted_data, uint16_t tag_data, uint8_t hdrversion, uint16_t tag_ivec, uint16_t hdrflags, uint16_t flag_256bitkey) { if (key && key->symkey.userKeyLength > 0) { /* we assume the data are encrypted when there's a key given */ return SWTPM_NVRAM_DecryptData(key, decrypt_data, decrypt_length, data, length, tag_encrypted_data, hdrversion, tag_ivec, hdrflags, flag_256bitkey); } return SWTPM_NVRAM_GetPlainData(decrypt_data, decrypt_length, data, length, tag_data, hdrversion); } /* * Prepend a header in front of the state blob */ static TPM_RESULT SWTPM_NVRAM_PrependHeader(unsigned char **data, uint32_t *length, uint16_t flags) { unsigned char *out = NULL; uint32_t out_len = sizeof(blobheader) + *length; blobheader bh = { .version = BLOB_HEADER_VERSION, .min_version = 1, .hdrsize = htons(sizeof(bh)), .flags = htons(flags), .totlen = htonl(out_len), }; TPM_RESULT res; out = malloc(out_len); if (!out) { logprintf(STDERR_FILENO, "Could not allocate %u bytes.\n", out_len); res = TPM_FAIL; goto error; } memcpy(out, &bh, sizeof(bh)); memcpy(&out[sizeof(bh)], *data, *length); free(*data); *data = out; *length = out_len; return TPM_SUCCESS; error: free(*data); *data = NULL; *length = 0; return res; } static TPM_RESULT SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length, uint32_t *dataoffset, uint16_t *hdrflags, uint8_t *hdrversion, bool quiet) { blobheader *bh = (blobheader *)data; uint16_t hdrsize; if (length < sizeof(bh)) { if (!quiet) logprintf(STDERR_FILENO, "not enough bytes for header: %u\n", length); return TPM_BAD_PARAMETER; } if (ntohl(bh->totlen) != length) { if (!quiet) logprintf(STDERR_FILENO, "broken header: bh->totlen %u != %u\n", htonl(bh->totlen), length); return TPM_BAD_PARAMETER; } if (bh->min_version > BLOB_HEADER_VERSION) { if (!quiet) logprintf(STDERR_FILENO, "Minimum required version for the blob is %d, we " "only support version %d\n", bh->min_version, BLOB_HEADER_VERSION); return TPM_BAD_VERSION; } hdrsize = ntohs(bh->hdrsize); if (hdrsize != sizeof(blobheader)) { logprintf(STDERR_FILENO, "bad header size: %u != %zu\n", hdrsize, sizeof(blobheader)); return TPM_BAD_DATASIZE; } *hdrversion = bh->version; *dataoffset = hdrsize; *hdrflags = ntohs(bh->flags); return TPM_SUCCESS; } /* * Get the state blob with the current name; read it from the filesystem. * Decrypt it if the caller asks for it and if a key is set. Return * whether it's still encrypyted. */ TPM_RESULT SWTPM_NVRAM_GetStateBlob(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name, TPM_BOOL decrypt, TPM_BOOL *is_encrypted) { TPM_RESULT res; uint16_t flags = 0; tlv_data td[3]; size_t td_len; unsigned char *plain = NULL, *buffer = NULL; uint32_t plain_len, buffer_len = 0; *data = NULL; *length = 0; res = SWTPM_NVRAM_LoadData(&plain, &plain_len, tpm_number, name); if (res) return res; /* @plain contains unencrypted data without tlv headers */ /* if the user doesn't want decryption and there's a file key, we need to encrypt the data */ if (!decrypt && SWTPM_NVRAM_Has_FileKey()) { td_len = 3; res = SWTPM_NVRAM_EncryptData(&filekey, &td[0], &td_len, TAG_ENCRYPTED_DATA, plain, plain_len, TAG_IVEC_ENCRYPTED_DATA); if (res) goto err_exit; *is_encrypted = TRUE; if (SWTPM_NVRAM_FileKey_Size() == SWTPM_AES256_BLOCK_SIZE) flags |= BLOB_FLAG_ENCRYPTED_256BIT_KEY; } else { *is_encrypted = FALSE; td[0] = TLV_DATA(TAG_DATA, plain_len, plain); plain = NULL; td_len = 1; } res = tlv_data_append(&buffer, &buffer_len, td, td_len); if (res) goto err_exit; tlv_data_free(td, td_len); /* @buffer contains tlv data */ if (SWTPM_NVRAM_Has_MigrationKey()) { /* we have to encrypt it now with the migration key */ flags |= BLOB_FLAG_MIGRATION_ENCRYPTED; if (SWTPM_NVRAM_MigrationKey_Size() == SWTPM_AES256_BLOCK_SIZE) flags |= BLOB_FLAG_MIGRATION_256BIT_KEY; td_len = 3; res = SWTPM_NVRAM_EncryptData(&migrationkey, &td[0], &td_len, TAG_ENCRYPTED_MIGRATION_DATA, buffer, buffer_len, TAG_IVEC_ENCRYPTED_MIGRATION_DATA); if (res) goto err_exit; } else { td[0] = TLV_DATA(TAG_MIGRATION_DATA, buffer_len, buffer); buffer = NULL; td_len = 1; } flags |= BLOB_FLAG_MIGRATION_DATA; res = tlv_data_append(data, length, td, td_len); if (res) goto err_exit; /* put the header in clear text */ if (*is_encrypted) flags |= BLOB_FLAG_ENCRYPTED; res = SWTPM_NVRAM_PrependHeader(data, length, flags); err_exit: tlv_data_free(td, td_len); free(buffer); free(plain); return res; } /* * Set the state blob with the given name; the caller tells us if * the blob is encrypted; if it is encrypted, it will be written * into the file as-is, otherwise it will be encrypted if a key is set. */ TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data, uint32_t length, TPM_BOOL is_encrypted, uint32_t tpm_number, uint32_t blobtype) { TPM_RESULT res; uint32_t dataoffset; unsigned char *plain = NULL, *mig_decrypt = NULL; uint32_t plain_len = 0, mig_decrypt_len = 0; uint16_t hdrflags; enum TPMLIB_StateType st = tpmlib_blobtype_to_statetype(blobtype); const char *blobname = tpmlib_get_blobname(blobtype); uint8_t hdrversion; if (st == 0) { logprintf(STDERR_FILENO, "Unknown blob type %u\n", blobtype); return TPM_BAD_PARAMETER; } if (length == 0) return TPMLIB_SetState(st, NULL, 0); res = SWTPM_NVRAM_CheckHeader(data, length, &dataoffset, &hdrflags, &hdrversion, false); if (res != TPM_SUCCESS) return res; if (length - dataoffset == 0) return TPMLIB_SetState(st, NULL, 0); /* * We allow setting of blobs that were not encrypted before; * we just will not decrypt them even if the migration key is * set. This allows to 'upgrade' to encryption. 'Downgrading' * will not be possible once a migration key was used. */ if ((hdrflags & BLOB_FLAG_MIGRATION_ENCRYPTED)) { /* * we first need to decrypt the data with the migration key */ if (!SWTPM_NVRAM_Has_MigrationKey()) { logprintf(STDERR_FILENO, "Missing migration key to decrypt %s\n", blobname); return TPM_KEYNOTFOUND; } res = SWTPM_NVRAM_DecryptData(&migrationkey, &mig_decrypt, &mig_decrypt_len, &data[dataoffset], length - dataoffset, TAG_ENCRYPTED_MIGRATION_DATA, hdrversion, TAG_IVEC_ENCRYPTED_MIGRATION_DATA, hdrflags, BLOB_FLAG_MIGRATION_256BIT_KEY); if (res) { logprintf(STDERR_FILENO, "Decrypting the %s blob with the migration key failed; " "res = %d\n", blobname, res); return res; } } else { res = SWTPM_NVRAM_GetPlainData(&mig_decrypt, &mig_decrypt_len, &data[dataoffset], length - dataoffset, TAG_MIGRATION_DATA, hdrversion); if (res) return res; } /* * Migration key has decrytped the data; if they are still encrypted * with the state encryption key, we need to decrypt them using that * key now. */ if (is_encrypted || (hdrflags & BLOB_FLAG_ENCRYPTED)) { if (!SWTPM_NVRAM_Has_FileKey()) { logprintf(STDERR_FILENO, "Missing state key to decrypt %s\n", blobname); res = TPM_KEYNOTFOUND; goto cleanup; } res = SWTPM_NVRAM_DecryptData(&filekey, &plain, &plain_len, mig_decrypt, mig_decrypt_len, TAG_ENCRYPTED_DATA, hdrversion, TAG_IVEC_ENCRYPTED_DATA, hdrflags, BLOB_FLAG_ENCRYPTED_256BIT_KEY); if (res) { logprintf(STDERR_FILENO, "Decrypting the %s blob with the state key " "failed; res = %d\n", blobname, res); goto cleanup; } } else { res = SWTPM_NVRAM_GetPlainData(&plain, &plain_len, mig_decrypt, mig_decrypt_len, TAG_DATA, hdrversion); if (res) goto cleanup; } /* SetState will make a copy of the buffer */ res = TPMLIB_SetState(st, plain, plain_len); free(plain); cleanup: free(mig_decrypt); return res; } swtpm-0.6.3/src/swtpm/swtpm_nvfile.h000066400000000000000000000113251421141172300175170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef _SWTPM_NVFILE_H #define _SWTPM_NVFILE_H #include #include "key.h" /* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc. This macro is used once during initialization to ensure that the TPM_PATH environment variable length will not cause the rooted file name to overflow file name buffers. */ #define TPM_FILENAME_MAX 20 #include TPM_RESULT SWTPM_NVRAM_Init(void); void SWTPM_NVRAM_Shutdown(void); void SWTPM_NVRAM_Set_TPMVersion(TPMLIB_TPMVersion version); /* Basic abstraction for read and write */ TPM_RESULT SWTPM_NVRAM_LoadData(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name); TPM_RESULT SWTPM_NVRAM_StoreData(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name); TPM_RESULT SWTPM_NVRAM_DeleteName(uint32_t tpm_number, const char *name, TPM_BOOL mustExist); TPM_RESULT SWTPM_NVRAM_Store_Volatile(void); TPM_RESULT SWTPM_NVRAM_Set_FileKey(const unsigned char *data, uint32_t length, enum encryption_mode mode); TPM_RESULT SWTPM_NVRAM_Set_MigrationKey(const unsigned char *data, uint32_t length, enum encryption_mode mode); TPM_RESULT SWTPM_NVRAM_GetStateBlob(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name, TPM_BOOL decrypt, TPM_BOOL *is_encrypted); TPM_RESULT SWTPM_NVRAM_SetStateBlob(unsigned char *data, uint32_t length, TPM_BOOL is_encrypted, uint32_t tpm_number, uint32_t blobtype); size_t SWTPM_NVRAM_FileKey_Size(void); static inline TPM_BOOL SWTPM_NVRAM_Has_FileKey(void) { return SWTPM_NVRAM_FileKey_Size() > 0; } size_t SWTPM_NVRAM_MigrationKey_Size(void); static inline TPM_BOOL SWTPM_NVRAM_Has_MigrationKey(void) { return SWTPM_NVRAM_MigrationKey_Size() > 0; } #endif /* _SWTPM_NVFILE_H */ swtpm-0.6.3/src/swtpm/threadpool.c000066400000000000000000000103131421141172300171320ustar00rootroot00000000000000/* * threadpool.c -- threadpool * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "threadpool.h" /* whether the worker thread is busy processing a command */ static bool thread_busy; /* thread pool with one single TPM thread */ GThreadPool *pool; #if GLIB_MAJOR_VERSION >= 2 # if GLIB_MINOR_VERSION >= 32 GCond thread_busy_signal; GMutex thread_busy_lock; # define THREAD_BUSY_SIGNAL &thread_busy_signal # define THREAD_BUSY_LOCK &thread_busy_lock # else GCond *thread_busy_signal; GMutex *thread_busy_lock; # define THREAD_BUSY_SIGNAL thread_busy_signal # define THREAD_BUSY_LOCK thread_busy_lock # endif #else #error Unsupport glib version #endif /* * worker_thread_wait_done: wait until the worker thread is done */ void worker_thread_wait_done(void) { g_mutex_lock(THREAD_BUSY_LOCK); while (thread_busy) { #if GLIB_MINOR_VERSION >= 32 gint64 end_time = g_get_monotonic_time() + 1 * G_TIME_SPAN_SECOND; g_cond_wait_until(THREAD_BUSY_SIGNAL, THREAD_BUSY_LOCK, end_time); #else GTimeVal abs_time; /* * seems like occasionally the g_cond_signal did not wake up * the sleeping task; so we poll [TIS Test in BIOS] */ abs_time.tv_sec = 1; abs_time.tv_usec = 0; g_cond_timed_wait(THREAD_BUSY_SIGNAL, THREAD_BUSY_LOCK, &abs_time); #endif } g_mutex_unlock(THREAD_BUSY_LOCK); } /* * worker_thread_mark_busy: mark the workder thread as busy */ void worker_thread_mark_busy(void) { g_mutex_lock(THREAD_BUSY_LOCK); thread_busy = true; g_mutex_unlock(THREAD_BUSY_LOCK); } /* * work_tread_mark_done: mark the worker thread as having completed * * Mark the worker thread as done and wake up the waiting thread. */ void worker_thread_mark_done(void) { g_mutex_lock(THREAD_BUSY_LOCK); thread_busy = false; g_cond_signal(THREAD_BUSY_SIGNAL); g_mutex_unlock(THREAD_BUSY_LOCK); } /* * worker_thread_is_busy: is the worker thread busy? * * Determine whether the worker thread is busy. */ int worker_thread_is_busy(void) { return thread_busy; } /* * worker_thread_end: cleanup once worker thread is all done */ void worker_thread_end(void) { if (pool) { worker_thread_wait_done(); g_thread_pool_free(pool, TRUE, TRUE); pool = NULL; } } void worker_thread_init(void) { #if GLIB_MINOR_VERSION >= 32 g_mutex_init(THREAD_BUSY_LOCK); g_cond_init(THREAD_BUSY_SIGNAL); #else g_thread_init(NULL); THREAD_BUSY_LOCK = g_mutex_new(); THREAD_BUSY_SIGNAL = g_cond_new(); #endif } swtpm-0.6.3/src/swtpm/threadpool.h000066400000000000000000000042451421141172300171460ustar00rootroot00000000000000/* * threadpool.h -- threadpool * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_THREADPOOL_H_ #define _SWTPM_THREADPOOL_H_ typedef enum { MESSAGE_TPM_CMD = 1, MESSAGE_IOCTL, } msg_type; /* the message we are sending to the thread in the pool */ struct thread_message { msg_type type; }; extern GThreadPool *pool; void worker_thread_wait_done(void); void worker_thread_mark_busy(void); void worker_thread_mark_done(void); int worker_thread_is_busy(void); void worker_thread_cuse(gpointer data, gpointer user_data); void worker_thread_end(void); void worker_thread_init(void); #endif /* _SWTPM_THREADPOOL_H_ */ swtpm-0.6.3/src/swtpm/tlv.c000066400000000000000000000107721421141172300156070ustar00rootroot00000000000000/* * tlc.v -- tag-length-value * * (c) Copyright IBM Corporation 2018. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "tlv.h" #include "logging.h" #include "sys_dependencies.h" #include #include #include #include void tlv_data_free(tlv_data *td, size_t td_len) { size_t i; for (i = 0; i < td_len; i++) { if (!td[i].is_const_ptr) free(td[i].u.ptr); memset(&td[i], 0, sizeof(*td)); } } /* * tlv_data_append: append data in tlv_data array to a buffer * @buffer: pointer to a pointer to a buffer or NULL if new buffer * @buffer_len: length of existing buffer; will hold size of new buffer on return * @td: array of tlv_data * @td_len: length of td array */ TPM_RESULT tlv_data_append(unsigned char **buffer, uint32_t *buffer_len, tlv_data *td, size_t td_len) { size_t i; tlv_header tlv; uint32_t totlen; size_t addlen = 0; unsigned char *ptr; unsigned char *tmp; for (i = 0; i < td_len; i++) addlen += sizeof(tlv) + td[i].tlv.length; if (*buffer) totlen = *buffer_len + addlen; else totlen = addlen; tmp = realloc(*buffer, totlen); if (!tmp) { logprintf(STDERR_FILENO, "Could not allocate %u bytes.\n", totlen); return TPM_FAIL; } *buffer = tmp; ptr = *buffer + *buffer_len; *buffer_len = totlen; for (i = 0; i < td_len; i++) { tlv.tag = htobe16(td[i].tlv.tag); tlv.length = htobe32(td[i].tlv.length); memcpy(ptr, &tlv, sizeof(tlv)); ptr += sizeof(tlv); if (td[i].is_const_ptr) memcpy(ptr, td[i].u.const_ptr, td[i].tlv.length); else memcpy(ptr, td[i].u.ptr, td[i].tlv.length); ptr += td[i].tlv.length; } return 0; } /* tlv_data_find_tag: in a byte stream that starts with a tlv_header, find a tlv_header with a given tag * @buffer: the buffer to search; must start with a tlv_header * @buffer_len: the length of the buffer * @tag: the tag to search for * @td: tlv_data pointer to receive the result in, * * Returns NULL if nothing was found, the pointer to the data corresponding * to the tag otherwise. */ const unsigned char * tlv_data_find_tag(const unsigned char *buffer, uint32_t buffer_len, uint16_t tag, tlv_data *td) { uint32_t offset = 0; while (offset < buffer_len) { if (offset + sizeof(td->tlv) > buffer_len) return NULL; memcpy(&td->tlv, buffer + offset, sizeof(td->tlv)); offset += sizeof(td->tlv); td->tlv.length = be32toh(td->tlv.length); if (offset + td->tlv.length > buffer_len) return NULL; td->tlv.tag = be16toh(td->tlv.tag); if (td->tlv.tag == tag) { td->is_const_ptr = true; td->u.const_ptr = &buffer[offset]; return buffer; } offset += td->tlv.length; } return NULL; } swtpm-0.6.3/src/swtpm/tlv.h000066400000000000000000000063611421141172300156130ustar00rootroot00000000000000/* * tlv.h -- tag-length-value * * (c) Copyright IBM Corporation 2018. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_TLV_H_ #define _SWTPM_TLV_H_ #include #include #include #include typedef struct tlv_header { uint16_t tag; uint32_t length; /* length of the data to follow excluding this header */ /* uint8_t data[0]; */ } __attribute((packed)) tlv_header; #define TAG_DATA 1 #define TAG_ENCRYPTED_DATA 2 #define TAG_HMAC 3 #define TAG_MIGRATION_DATA 4 #define TAG_ENCRYPTED_MIGRATION_DATA 5 #define TAG_IVEC_ENCRYPTED_DATA 6 #define TAG_IVEC_ENCRYPTED_MIGRATION_DATA 7 typedef struct tlv_data { struct tlv_header tlv; bool is_const_ptr; union { uint8_t *ptr; const uint8_t *const_ptr; } u; } tlv_data; #define _TLV_DATA(TAG, LENGTH, IS_CONST_PTR, PTR_FIELD) \ (tlv_data) { \ .tlv.tag = TAG, \ .tlv.length = LENGTH, \ .is_const_ptr = IS_CONST_PTR, \ PTR_FIELD, \ } #define TLV_DATA(TAG, LENGTH, PTR) _TLV_DATA(TAG, LENGTH, false,\ .u.ptr = PTR) #define TLV_DATA_CONST(TAG, LENGTH, PTR) _TLV_DATA(TAG, LENGTH, true ,\ .u.const_ptr = PTR) void tlv_data_free(tlv_data *td, size_t td_len); TPM_RESULT tlv_data_append(unsigned char **buffer, uint32_t *buffer_len, tlv_data *td, size_t td_len); const unsigned char *tlv_data_find_tag(const unsigned char *buffer, uint32_t buffer_len, uint16_t tag, tlv_data *td); #endif /* _SWTPM_TLV_H_ */ swtpm-0.6.3/src/swtpm/tpmlib.c000066400000000000000000000345721421141172300162750ustar00rootroot00000000000000/* * tpm_funcs.c -- interface with libtpms * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "sys_dependencies.h" #include #include #include #include #include #include #include #include "tpmlib.h" #include "logging.h" #include "tpm_ioctl.h" #include "swtpm_nvfile.h" #include "locality.h" #ifdef WITH_VTPM_PROXY #include "vtpm_proxy.h" #endif #include "utils.h" /* * convert the blobtype integer into a string that libtpms * understands */ const char *tpmlib_get_blobname(uint32_t blobtype) { switch (blobtype) { case PTM_BLOB_TYPE_PERMANENT: return TPM_PERMANENT_ALL_NAME; case PTM_BLOB_TYPE_VOLATILE: return TPM_VOLATILESTATE_NAME; case PTM_BLOB_TYPE_SAVESTATE: return TPM_SAVESTATE_NAME; default: return NULL; } } TPM_RESULT tpmlib_register_callbacks(struct libtpms_callbacks *cbs) { TPM_RESULT res; if ((res = TPMLIB_RegisterCallbacks(cbs)) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not register the callbacks.\n"); } return res; } TPM_RESULT tpmlib_start(uint32_t flags, TPMLIB_TPMVersion tpmversion) { TPM_RESULT res; if ((res = TPMLIB_ChooseTPMVersion(tpmversion)) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not choose TPM 2 implementation.\n"); return res; } if ((res = TPMLIB_MainInit()) != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not initialize libtpms.\n"); return res; } if (flags & PTM_INIT_FLAG_DELETE_VOLATILE) { uint32_t tpm_number = 0; char *name = TPM_VOLATILESTATE_NAME; res = SWTPM_NVRAM_DeleteName(tpm_number, name, FALSE); if (res != TPM_SUCCESS) { logprintf(STDERR_FILENO, "Error: Could not delete the volatile " "state of the TPM.\n"); goto error_terminate; } } return TPM_SUCCESS; error_terminate: TPMLIB_Terminate(); return res; } int tpmlib_get_tpm_property(enum TPMLIB_TPMProperty prop) { int result; TPM_RESULT res; res = TPMLIB_GetTPMProperty(prop, &result); assert(res == TPM_SUCCESS); return result; } bool tpmlib_is_request_cancelable(TPMLIB_TPMVersion tpmversion, const unsigned char *request, size_t req_len) { struct tpm_req_header *hdr; uint32_t ordinal; if (req_len < sizeof(struct tpm_req_header)) return false; hdr = (struct tpm_req_header *)request; ordinal = be32toh(hdr->ordinal); if (tpmversion == TPMLIB_TPM_VERSION_2) return (ordinal == TPMLIB_TPM2_CC_CreatePrimary || ordinal == TPMLIB_TPM2_CC_Create); return (ordinal == TPMLIB_TPM_ORD_TakeOwnership || ordinal == TPMLIB_TPM_ORD_CreateWrapKey); } static void tpmlib_write_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPM_RESULT errcode, TPMLIB_TPMVersion tpmversion) { struct tpm_resp_header errresp = { .tag = (tpmversion == TPMLIB_TPM_VERSION_2) ? htobe16(0x8001) : htobe16(0xc4), .size = htobe32(sizeof(errresp)), .errcode = htobe32(errcode), }; if (*rbuffer == NULL || *rTotal < sizeof(errresp)) { free(*rbuffer); *rbuffer = malloc(sizeof(errresp)); if (*rbuffer) *rTotal = sizeof(errresp); else *rTotal = 0; } if (*rbuffer) { *rlength = sizeof(errresp); memcpy(*rbuffer, &errresp, sizeof(errresp)); } } void tpmlib_write_fatal_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion) { TPM_RESULT errcode = (tpmversion == TPMLIB_TPM_VERSION_2) ? TPM_RC_FAILURE : TPM_FAIL; tpmlib_write_error_response(rbuffer, rlength, rTotal, errcode, tpmversion); } void tpmlib_write_locality_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion) { TPM_RESULT errcode = (tpmversion == TPMLIB_TPM_VERSION_2) ? TPM_RC_LOCALITY : TPM_BAD_LOCALITY; tpmlib_write_error_response(rbuffer, rlength, rTotal, errcode, tpmversion); } void tpmlib_write_success_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion) { tpmlib_write_error_response(rbuffer, rlength, rTotal, 0, tpmversion); } #ifdef WITH_VTPM_PROXY static void tpmlib_write_shortmsg_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion) { TPM_RESULT errcode = (tpmversion == TPMLIB_TPM_VERSION_2) ? TPM_RC_INSUFFICIENT : TPM_BAD_PARAM_SIZE; tpmlib_write_error_response(rbuffer, rlength, rTotal, errcode, tpmversion); } static TPM_RESULT tpmlib_process_setlocality(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, unsigned char *command, uint32_t command_length, TPMLIB_TPMVersion tpmversion, uint32_t locality_flags, TPM_MODIFIER_INDICATOR *locality) { TPM_MODIFIER_INDICATOR new_locality; if (command_length >= sizeof(struct tpm_req_header) + sizeof(char)) { if (!(locality_flags & LOCALITY_FLAG_ALLOW_SETLOCALITY)) { /* SETLOCALITY command is not allowed */ tpmlib_write_fatal_error_response(rbuffer, rlength, rTotal, tpmversion); } else { new_locality = command[sizeof(struct tpm_req_header)]; if (new_locality >=5 || (new_locality == 4 && locality_flags & LOCALITY_FLAG_REJECT_LOCALITY_4)) { tpmlib_write_locality_error_response(rbuffer, rlength, rTotal, tpmversion); } else { tpmlib_write_success_response(rbuffer, rlength, rTotal, tpmversion); *locality = new_locality; } } } else { tpmlib_write_shortmsg_error_response(rbuffer, rlength, rTotal, tpmversion); } return TPM_SUCCESS; } TPM_RESULT tpmlib_process(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, unsigned char *command, uint32_t command_length, uint32_t locality_flags, TPM_MODIFIER_INDICATOR *locality, TPMLIB_TPMVersion tpmversion) { /* process those commands we need to handle, e.g. SetLocality */ struct tpm_req_header *req = (struct tpm_req_header *)command; uint32_t ordinal; if (command_length < sizeof(*req)) { tpmlib_write_shortmsg_error_response(rbuffer, rlength, rTotal, tpmversion); return TPM_SUCCESS; } ordinal = be32toh(req->ordinal); switch (tpmversion) { case TPMLIB_TPM_VERSION_1_2: switch (ordinal) { case TPM_CC_SET_LOCALITY: return tpmlib_process_setlocality(rbuffer, rlength, rTotal, command, command_length, tpmversion, locality_flags, locality); } break; case TPMLIB_TPM_VERSION_2: switch (ordinal) { case TPM2_CC_SET_LOCALITY: return tpmlib_process_setlocality(rbuffer, rlength, rTotal, command, command_length, tpmversion, locality_flags, locality); } break; } return TPM_SUCCESS; } #else TPM_RESULT tpmlib_process(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, unsigned char *command, uint32_t command_length, uint32_t locality_flags, TPM_MODIFIER_INDICATOR *locality, TPMLIB_TPMVersion tpmversion) { return TPM_SUCCESS; } #endif /* WITH_VTPM_PROXY */ enum TPMLIB_StateType tpmlib_blobtype_to_statetype(uint32_t blobtype) { switch (blobtype) { case PTM_BLOB_TYPE_PERMANENT: return TPMLIB_STATE_PERMANENT; case PTM_BLOB_TYPE_VOLATILE: return TPMLIB_STATE_VOLATILE; case PTM_BLOB_TYPE_SAVESTATE: return TPMLIB_STATE_SAVE_STATE; } return 0; } /* * tpmlib_handle_tcg_tpm2_cmd_header * * Determine whether the given byte stream is a raw TPM 2 command or * whether it has a tcg_tpm2_cmd_header prefixed and if so return * the offset after the header where the actual command is. In all * other cases return 0. */ off_t tpmlib_handle_tcg_tpm2_cmd_header(const unsigned char *command, uint32_t command_length, TPM_MODIFIER_INDICATOR *locality) { struct tpm_req_header *hdr = (struct tpm_req_header *)command; struct tpm2_send_command_prefix *tcgprefix; off_t ret = 0; /* return 0 for short packets or plain TPM 2 command */ if (command_length < sizeof(*hdr) || be16toh(hdr->tag) == TPM2_ST_NO_SESSION || be16toh(hdr->tag) == TPM2_ST_SESSIONS || command_length < sizeof(*tcgprefix)) return 0; tcgprefix = (struct tpm2_send_command_prefix *)command; if (be32toh(tcgprefix->cmd) == TPM2_SEND_COMMAND) { ret = sizeof(*tcgprefix); *locality = tcgprefix->locality; } return ret; } /* * Create a Startup command with the given startupType for the * given TPM version. */ uint32_t tpmlib_create_startup_cmd(uint16_t startupType, TPMLIB_TPMVersion tpmversion, unsigned char *buffer, uint32_t buffersize) { struct tpm_startup ts; uint32_t tocopy = min(sizeof(ts), buffersize); ts.hdr.size = htobe32(sizeof(ts)); switch (tpmversion) { case TPMLIB_TPM_VERSION_1_2: ts.hdr.tag = htobe16(TPM_TAG_RQU_COMMAND); ts.hdr.ordinal = htobe32(TPMLIB_TPM_ORD_Startup); ts.startupType = htobe16(startupType); break; case TPMLIB_TPM_VERSION_2: ts.hdr.tag = htobe16(TPM2_ST_NO_SESSION); ts.hdr.ordinal = htobe32(TPMLIB_TPM2_CC_Startup); switch (startupType) { case TPM_ST_CLEAR: ts.startupType = htobe16(TPM2_SU_CLEAR); break; case TPM_ST_STATE: ts.startupType = htobe16(TPM2_SU_STATE); break; case TPM_ST_DEACTIVATED: tocopy = 0; logprintf(STDERR_FILENO, "TPM 2 does not support startup deactivated.\n"); break; default: tocopy = 0; logprintf(STDERR_FILENO, "%s: internal error; unupported startup type for TPM 2\n", __func__); break; } break; default: tocopy = 0; logprintf(STDERR_FILENO, "%s: internal error; invalid TPM version\n", __func__); break; } if (tocopy) memcpy(buffer, &ts, tocopy); return tocopy; } swtpm-0.6.3/src/swtpm/tpmlib.h000066400000000000000000000130001421141172300162610ustar00rootroot00000000000000/* * tpmlib.h -- interface with libtpms * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_TPMLIB_H_ #define _SWTPM_TPMLIB_H_ #include #include #include const char *tpmlib_get_blobname(uint32_t blobtype); enum TPMLIB_StateType tpmlib_blobtype_to_statetype(uint32_t blobtype); TPM_RESULT tpmlib_register_callbacks(struct libtpms_callbacks *cbs); TPM_RESULT tpmlib_start(uint32_t flags, TPMLIB_TPMVersion tpmversion); int tpmlib_get_tpm_property(enum TPMLIB_TPMProperty prop); bool tpmlib_is_request_cancelable(TPMLIB_TPMVersion tpmversion, const unsigned char *request, size_t req_len); void tpmlib_write_fatal_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion); void tpmlib_write_locality_error_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion); void tpmlib_write_success_response(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, TPMLIB_TPMVersion tpmversion); TPM_RESULT tpmlib_process(unsigned char **rbuffer, uint32_t *rlength, uint32_t *rTotal, unsigned char *command, uint32_t command_length, uint32_t locality_flags, TPM_MODIFIER_INDICATOR *locality, TPMLIB_TPMVersion tpmversion); off_t tpmlib_handle_tcg_tpm2_cmd_header(const unsigned char *command, uint32_t command_length, TPM_MODIFIER_INDICATOR *locality); uint32_t tpmlib_create_startup_cmd(uint16_t startupType, TPMLIB_TPMVersion tpmversion, unsigned char *buffer, uint32_t buffersize); struct tpm_req_header { uint16_t tag; uint32_t size; uint32_t ordinal; } __attribute__((packed)); struct tpm_resp_header { uint16_t tag; uint32_t size; uint32_t errcode; } __attribute__((packed)); struct tpm2_send_command_prefix { uint32_t cmd; uint8_t locality; uint32_t size; /* size of the following TPM request */ } __attribute__((packed)); struct tpm2_resp_prefix { uint32_t size; /* size of the following TPM response */ } __attribute__((packed)); /* TPM 1.2 and TPM 2 used the same structured for startup */ struct tpm_startup { struct tpm_req_header hdr; uint16_t startupType; } __attribute__((packed)); /* Commands in tcg_tpm2_cmd_header 'cmd' */ #define TPM2_SEND_COMMAND 8 /* Tags supported by TPM2 */ #define TPM2_ST_NO_SESSION 0x8001 #define TPM2_ST_SESSIONS 0x8002 /* Tags supported by TPM 1.2 */ #define TPM_TAG_RQU_COMMAND 0x00C1 /* TPM 1.2 ordinals */ #define TPMLIB_TPM_ORD_TakeOwnership 0x0000000d #define TPMLIB_TPM_ORD_CreateWrapKey 0x0000001f #define TPMLIB_TPM_ORD_Startup 0x00000099 /* TPM 1.2 startup types */ #define TPM_ST_CLEAR 0x0001 #define TPM_ST_STATE 0x0002 #define TPM_ST_DEACTIVATED 0x0003 #define _TPM_ST_NONE 0x0000 /* do not send Startup */ /* TPM 2 error codes */ #define TPM_RC_INSUFFICIENT 0x09a #define TPM_RC_FAILURE 0x101 #define TPM_RC_LOCALITY 0x107 /* TPM 2 commands */ #define TPMLIB_TPM2_CC_CreatePrimary 0x00000131 #define TPMLIB_TPM2_CC_Startup 0x00000144 #define TPMLIB_TPM2_CC_Create 0x00000153 /* TPM 2 startup types */ #define TPM2_SU_CLEAR 0x0000 #define TPM2_SU_STATE 0x0001 #endif /* _SWTPM_TPMLIB_H_ */ swtpm-0.6.3/src/swtpm/tpmstate.c000066400000000000000000000046301421141172300166370ustar00rootroot00000000000000/* * tpmstate.c -- tpmstate parameter handling * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include "tpmstate.h" #include "logging.h" static char *g_tpmstatedir; static mode_t g_tpmstate_mode = 0640; int tpmstate_set_dir(char *tpmstatedir) { g_tpmstatedir = strdup(tpmstatedir); if (!g_tpmstatedir) { logprintf(STDERR_FILENO, "Out of memory.\n"); return -1; } return 0; } void tpmstate_global_free(void) { free(g_tpmstatedir); g_tpmstatedir = NULL; } const char *tpmstate_get_dir(void) { if (g_tpmstatedir) return g_tpmstatedir; return getenv("TPM_PATH"); } int tpmstate_set_mode(mode_t mode) { g_tpmstate_mode = mode; return 0; } mode_t tpmstate_get_mode(void) { return g_tpmstate_mode; } swtpm-0.6.3/src/swtpm/tpmstate.h000066400000000000000000000036441421141172300166500ustar00rootroot00000000000000/* * tpmstate.h -- tpmstate parameter handling * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_TPMSTATE_H_ #define _SWTPM_TPMSTATE_H_ #include int tpmstate_set_dir(char *tpmstatdir); const char *tpmstate_get_dir(void); int tpmstate_set_mode(mode_t mode); mode_t tpmstate_get_mode(void); void tpmstate_global_free(void); #endif /* _SWTPM_TPMSTATE_H_ */ swtpm-0.6.3/src/swtpm/utils.c000066400000000000000000000221631421141172300161370ustar00rootroot00000000000000/* * utils.s -- utilities * * (c) Copyright IBM Corporation 2014, 2015, 2019. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #if defined __APPLE__ #include #include #endif #include "utils.h" #include "logging.h" #include "tpmlib.h" #include "swtpm_debug.h" void uninstall_sighandlers() { if (signal(SIGTERM, SIG_DFL) == SIG_ERR) logprintf(STDERR_FILENO, "Could not uninstall signal handler for SIGTERM.\n"); if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) logprintf(STDERR_FILENO, "Could not uninstall signal handler for SIGPIPE.\n"); } int install_sighandlers(int pipefd[2], sighandler_t handler) { if (pipe(pipefd) < 0) { logprintf(STDERR_FILENO, "Error: Could not open pipe.\n"); goto err_exit; } if (signal(SIGTERM, handler) == SIG_ERR) { logprintf(STDERR_FILENO, "Could not install signal handler for SIGTERM.\n"); goto err_close_pipe; } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { logprintf(STDERR_FILENO, "Could not install signal handler for SIGPIPE.\n"); goto err_close_pipe; } return 0; err_close_pipe: close(pipefd[0]); pipefd[0] = -1; close(pipefd[1]); pipefd[1] = -1; err_exit: return -1; } int change_process_owner(const char *user) { struct passwd *passwd; long int uid, gid; char *endptr = NULL; uid = strtoul(user, &endptr, 10); if (*endptr != '\0') { /* a string */ passwd = getpwnam(user); if (!passwd) { logprintf(STDERR_FILENO, "Error: User '%s' does not exist.\n", user); return -14; } if (initgroups(passwd->pw_name, passwd->pw_gid) < 0) { logprintf(STDERR_FILENO, "Error: initgroups(%s, %d) failed.\n", passwd->pw_name, passwd->pw_gid); return -10; } gid = passwd->pw_gid; uid = passwd->pw_uid; } else { /* an integer */ if ((unsigned long int)uid > UINT_MAX) { logprintf(STDERR_FILENO, "Error: uid %s outside valid range.\n", user); return -13; } gid = uid; } if (setgid(gid) < 0) { logprintf(STDERR_FILENO, "Error: setgid(%d) failed.\n", gid); return -11; } if (setuid(uid) < 0) { logprintf(STDERR_FILENO, "Error: setuid(%d) failed.\n", uid); return -12; } return 0; } void tpmlib_debug_libtpms_parameters(TPMLIB_TPMVersion tpmversion) { switch (tpmversion) { case TPMLIB_TPM_VERSION_1_2: TPM_DEBUG("TPM 1.2: Compiled for %u auth, %u transport, " "and %u DAA session slots\n", tpmlib_get_tpm_property(TPMPROP_TPM_MIN_AUTH_SESSIONS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_TRANS_SESSIONS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_DAA_SESSIONS)); TPM_DEBUG("TPM 1.2: Compiled for %u key slots, %u owner evict slots\n", tpmlib_get_tpm_property(TPMPROP_TPM_KEY_HANDLES), tpmlib_get_tpm_property(TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES)); TPM_DEBUG("TPM 1.2: Compiled for %u counters, %u saved sessions\n", tpmlib_get_tpm_property(TPMPROP_TPM_MIN_COUNTERS), tpmlib_get_tpm_property(TPMPROP_TPM_MIN_SESSION_LIST)); TPM_DEBUG("TPM 1.2: Compiled for %u family, " "%u delegate table entries\n", tpmlib_get_tpm_property(TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN), tpmlib_get_tpm_property(TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN)); TPM_DEBUG("TPM 1.2: Compiled for %u total NV, %u savestate, " "%u volatile space\n", tpmlib_get_tpm_property(TPMPROP_TPM_MAX_NV_SPACE), tpmlib_get_tpm_property(TPMPROP_TPM_MAX_SAVESTATE_SPACE), tpmlib_get_tpm_property(TPMPROP_TPM_MAX_VOLATILESTATE_SPACE)); #if 0 TPM_DEBUG("TPM1.2: Compiled for %u NV defined space\n", tpmlib_get_tpm_property(TPMPROP_TPM_MAX_NV_DEFINED_SIZE)); #endif break; case TPMLIB_TPM_VERSION_2: break; } } char *fd_to_filename(int fd) { #if defined __linux__ char buffer[64]; char *path; snprintf(buffer, sizeof(buffer), "/proc/self/fd/%d", fd); path = realpath(buffer, NULL); if (!path) { logprintf(STDERR_FILENO, "Could not read %s: %s\n", buffer, strerror(errno)); return NULL; } return path; #elif defined __APPLE__ char *path = malloc(MAXPATHLEN); if (!path) { logprintf(STDERR_FILENO, "Out of memory.\n"); return NULL; } if (fcntl(fd, F_GETPATH, path) < 0) { logprintf(STDERR_FILENO, "fcntl for F_GETPATH failed: %\n", strerror(errno)); free(path); return NULL; } return path; #else logprintf(STDERR_FILENO, "Cannot convert file descriptor to filename on this platform.\n"); return NULL; #endif } /* * write_full: Write all bytes of a buffer into the file descriptor * and handle partial writes on the way. * * @fd: file descriptor to write to * @buffer: buffer * @buflen: length of buffer * * Returns -1 in case not all bytes could be transferred, number of * bytes written otherwise (must be equal to buflen). */ ssize_t write_full(int fd, const void *buffer, size_t buflen) { size_t written = 0; ssize_t n; while (written < buflen) { n = write(fd, buffer, buflen - written); if (n == 0) return -1; if (n < 0) { if (errno == EINTR) continue; return -1; } written += n; buffer += n; } return written; } /* * writev_full: Write all bytes of an iovec into the file descriptor * and handle partial writes on the way. * @fd: file descriptor to write to * @iov: pointer to iov * @iovcnt: length of iov array * * Returns -1 in case not all bytes could be transferred, number of * bytes written otherwise (must be equal to buflen). */ ssize_t writev_full(int fd, const struct iovec *iov, int iovcnt) { int i; size_t off; unsigned char *buf; ssize_t n; size_t bytecount = 0; size_t numbufs = 0; size_t lastidx = -1; for (i = 0; i < iovcnt; i++) { if (iov[i].iov_len) { bytecount += iov[i].iov_len; numbufs++; lastidx = i; } } if (numbufs == 1) return write_full(fd, iov[lastidx].iov_base, iov[lastidx].iov_len); buf = malloc(bytecount); if (!buf) { errno = ENOMEM; return -1; } off = 0; for (i = 0; i < iovcnt; i++) { if (!iov[i].iov_len) continue; memcpy(&buf[off], iov[i].iov_base, iov[i].iov_len); off += iov[i].iov_len; } n = write_full(fd, buf, off); free(buf); return n; } /* * read_einter: Read bytes from a file descriptor into a buffer * and handle EINTR. Perform one read(). * * @fd: file descriptor to read from * @buffer: buffer * @buflen: length of buffer * * Returns -1 in case an error occurred, number of bytes read otherwise. */ ssize_t read_eintr(int fd, void *buffer, size_t buflen) { ssize_t n; while (true) { n = read(fd, buffer, buflen); if (n < 0) { if (errno == EINTR) continue; return -1; } return n; } } swtpm-0.6.3/src/swtpm/utils.h000066400000000000000000000045001421141172300161370ustar00rootroot00000000000000/* * utils.h -- utilities * * (c) Copyright IBM Corporation 2015. * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_UTILS_H_ #define _SWTPM_UTILS_H_ #include "config.h" #include #include #include #define min(a,b) ((a) < (b) ? (a) : (b)) #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) typedef void (*sighandler_t)(int); int install_sighandlers(int pipefd[2], sighandler_t handler); void uninstall_sighandlers(void); int change_process_owner(const char *owner); void tpmlib_debug_libtpms_parameters(TPMLIB_TPMVersion); char *fd_to_filename(int fd); ssize_t write_full(int fd, const void *buffer, size_t buflen); ssize_t writev_full(int fd, const struct iovec *iov, int iovcnt); ssize_t read_eintr(int fd, void *buffer, size_t buflen); #endif /* _SWTPM_UTILS_H_ */ swtpm-0.6.3/src/swtpm/vtpm_proxy.h000066400000000000000000000042551421141172300172350ustar00rootroot00000000000000/* * vtpm_proxy.h -- The Linux VTPM proxy device * * (c) Copyright IBM Corporation 2017 * * Author: Stefan Berger * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_VTPM_PROXY_H_ #define _SWTPM_VTPM_PROXY_H_ #include struct vtpm_proxy_new_dev { uint32_t flags; /* in */ uint32_t tpm_num; /* out */ uint32_t fd; /* out */ uint32_t major; /* out */ uint32_t minor; /* out */ }; #define VTPM_PROXY_FLAG_TPM2 1 /* vendor specific commands to set locality */ #define TPM2_CC_SET_LOCALITY 0x20001000 #define TPM_CC_SET_LOCALITY 0x20001000 #define VTPM_PROXY_IOC_NEW_DEV _IOWR(0xa1, 0x00, struct vtpm_proxy_new_dev) #endif /* _SWTPM_VTPM_PROXY_H_ */ swtpm-0.6.3/src/swtpm_bios/000077500000000000000000000000001421141172300156435ustar00rootroot00000000000000swtpm-0.6.3/src/swtpm_bios/Makefile.am000066400000000000000000000007571421141172300177100ustar00rootroot00000000000000# # src/swtpm_bios/Makefile.am # # For the license, see the LICENSE file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = \ tpm_bios.h bin_PROGRAMS = \ swtpm_bios swtpm_bios_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ $(MY_CFLAGS) \ $(CFLAGS) \ $(HARDENING_CFLAGS) swtpm_bios_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) swtpm_bios_SOURCES = tpm_bios.c EXTRA_DIST = \ README CLEANFILES = *.gcno *.gcda *.gcov swtpm-0.6.3/src/swtpm_bios/README000066400000000000000000000002641421141172300165250ustar00rootroot00000000000000swtpm_bios is a tool that sends those commands to a TPM that typically the firmware (BIOS) is supposed to send to it. For further information, check the manpage 'man swtpm_bios'. swtpm-0.6.3/src/swtpm_bios/tpm_bios.c000066400000000000000000000477741421141172300176460ustar00rootroot00000000000000/* * tpm_bios -- * * Authors: Ken Goldman * Stefan Berger * * (c) Copyright IBM Corporation 2014. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sys_dependencies.h" #include "swtpm.h" #include "tpm_bios.h" /* * durations of the commands * On slow machines with much concurrency short timeouts may result in * errors; so we scale them up by 10. */ #define TPM_DURATION_SHORT (2 * 10) /* seconds */ #define TPM_DURATION_MEDIUM (20 * 10) /* seconds */ #define TPM_DURATION_LONG (60 * 10) /* seconds */ #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define DEFAULT_TCP_PORT 6545 static char *tpm_device; /* e.g., /dev/tpm0 */ static char *tcp_hostname; static int tcp_port = DEFAULT_TCP_PORT; static char *unix_path; static int parse_tcp_optarg(char *optarg, char **tcp_hostname, int *tcp_port) { char *pos = strrchr(optarg, ':'); int n; *tcp_port = DEFAULT_TCP_PORT; if (!pos) { /* */ *tcp_hostname = strdup(optarg); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } return 0; } else if (pos == optarg) { if (strlen(&pos[1]) != 0) { /* : (not just ':') */ n = sscanf(&pos[1], "%u", tcp_port); if (n != 1) { fprintf(stderr, "Invalid port '%s'\n", &pos[1]); return -1; } if (*tcp_port >= 65536) { fprintf(stderr, "Port '%s' outside valid range.\n", &optarg[1]); return -1; } } *tcp_hostname = strdup("127.0.0.1"); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } } else { /* : */ n = sscanf(&pos[1], "%u", tcp_port); if (n != 1) { fprintf(stderr, "Invalid port '%s'\n", &pos[1]); return -1; } if (*tcp_port >= 65536) { fprintf(stderr, "Port '%s' outside valid range.\n", &optarg[1]); return -1; } *tcp_hostname = strndup(optarg, pos - optarg); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } } return 0; } static int open_connection(char *devname, char *tcp_device_hostname, int tcp_device_port, const char *unix_path) { int fd = -1; char *tcp_device_port_string = NULL; if (devname) goto use_device; if (tcp_device_hostname) goto use_tcp; if (unix_path) { struct sockaddr_un addr; size_t unix_path_len = strlen(unix_path) + 1; if (unix_path_len > sizeof(addr.sun_path)) { fprintf(stderr, "Socket path is too long.\n"); return -1; } fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd > 0) { addr.sun_family = AF_UNIX; strncpy(addr.sun_path, unix_path, unix_path_len); if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { close(fd); fd = -1; } } if (fd < 0) { fprintf(stderr, "Could not connect using UnixIO socket.\n"); } return fd; } if (getenv("TCSD_USE_TCP_DEVICE")) { struct addrinfo hints; struct addrinfo *ais = NULL, *ai; char portstr[10]; int err; if ((tcp_device_hostname = getenv("TCSD_TCP_DEVICE_HOSTNAME")) == NULL) tcp_device_hostname = "localhost"; if ((tcp_device_port_string = getenv("TCSD_TCP_DEVICE_PORT")) != NULL) tcp_device_port = atoi(tcp_device_port_string); else tcp_device_port = DEFAULT_TCP_PORT; use_tcp: memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%u", tcp_device_port); err = getaddrinfo(tcp_device_hostname, portstr, &hints, &ais); if (err != 0) { fprintf(stderr, "getaddrinfo failed on host '%s': %s\n", tcp_device_hostname, gai_strerror(err)); return -1; } for (ai = ais; ai != NULL; ai = ai->ai_next) { fd = socket(ai->ai_family, ai->ai_socktype, 0); if (fd < 0) continue; if (connect(fd, (struct sockaddr *)ai->ai_addr, ai->ai_addrlen) == 0) break; close(fd); fd = -1; } freeaddrinfo(ais); if (fd < 0) { fprintf(stderr, "Could not connect using TCP socket.\n"); } } else { use_device: if (!devname) devname = getenv("TPM_DEVICE"); if (!devname) devname = "/dev/tpm0"; fd = open(devname, O_RDWR); if (fd < 0) { fprintf(stderr, "Unable to open device '%s'.\n", devname ); } } return fd; } static int talk(const void *cmd, size_t count, int *tpm_errcode, unsigned int to_seconds, struct tpm_resp_header *res, size_t res_size) { ssize_t len; size_t pkt_len; int rc = -1; int fd, n; unsigned char buffer[1024]; struct timeval timeout = { .tv_sec = to_seconds, .tv_usec = 0, }; fd_set rfds; struct tpm_resp_header *hdr; fd = open_connection(tpm_device, tcp_hostname, tcp_port, unix_path); if (fd < 0) { goto err_exit; } len = write(fd, cmd, count); if (len < 0 || (size_t)len != count) { fprintf(stderr, "Write to file descriptor failed.\n"); goto err_close_fd; } FD_ZERO(&rfds); FD_SET(fd, &rfds); n = select(fd + 1, &rfds, NULL, NULL, &timeout); if (n == 0) { fprintf(stderr, "TPM did not respond after %u seconds.\n", to_seconds); goto err_close_fd; } else if (n < 0) { fprintf(stderr, "Error on select call: %s\n", strerror(errno)); goto err_close_fd; } len = read(fd, buffer, sizeof(buffer)); if (len < 0) { fprintf(stderr, "Read from file descriptor failed.\n"); goto err_close_fd; } if (len < 10) { fprintf(stderr, "Returned packet is too short.\n"); goto err_close_fd; } hdr = (struct tpm_resp_header *)buffer; pkt_len = be32toh(hdr->length); if ((unsigned int)len != pkt_len) { fprintf(stderr, "Malformed response.\n"); goto err_close_fd; } if (res) memcpy(res, buffer, MIN(pkt_len, res_size)); *tpm_errcode = be32toh(hdr->result); rc = 0; err_close_fd: close(fd); fd = -1; err_exit: return rc; } static int TPM_Startup(unsigned char parm, int *tpm_errcode) { struct tpm_startup tss = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tss)), .ordinal = htobe32(TPM_ORD_Startup), }, .startup_type = htobe16(parm), }; return talk(&tss, sizeof(tss), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TSC_PhysicalPresence(unsigned short physical_presence, int *tpm_errcode) { struct tsc_physical_presence tpp = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tpp)), .ordinal = htobe32(TPM_ORD_PhysicalPresence), }, .physical_presence = htobe16(physical_presence), }; return talk(&tpp, sizeof(tpp), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TPM_GetCapability_Subcap(uint32_t cap, uint32_t subcap, struct tpm_resp_header *res, size_t res_size, int *tpm_errcode) { struct tpm_get_capability_subcap tgc = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tgc)), .ordinal = htobe32(TPM_ORD_GetCapability), }, .cap = htobe32(cap), .subcap_size = htobe32(sizeof(tgc.subcap)), .subcap = htobe32(subcap), }; return talk(&tgc, sizeof(tgc), tpm_errcode, TPM_DURATION_SHORT, res, res_size); } static int TPM_PhysicalEnable(int *tpm_errcode) { struct tpm_physical_enable tpe = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tpe)), .ordinal = htobe32(TPM_ORD_PhysicalEnable), }, }; return talk(&tpe, sizeof(tpe), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TPM_PhysicalSetDeactivated(unsigned char parm, int *tpm_errcode) { struct tpm_physical_set_deactivated tpsd = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tpsd)), .ordinal = htobe32(TPM_ORD_PhysicalSetDeactivated), }, .state = parm, }; return talk(&tpsd, sizeof(tpsd), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TPM_ContinueSelfTest(int *tpm_errcode) { struct tpm_continue_selftest tcs = { .hdr = { .tag = htobe16(TPM_TAG_RQU_COMMAND), .length = htobe32(sizeof(tcs)), .ordinal = htobe32(TPM_ORD_ContinueSelfTest), }, }; return talk(&tcs, sizeof(tcs), tpm_errcode, TPM_DURATION_LONG, NULL, 0); } static int TPM2_Startup(unsigned short startup_type, int *tpm_errcode) { struct tpm2_startup ts = { .hdr = { .tag = htobe16(TPM2_ST_NO_SESSIONS), .length = htobe32(sizeof(ts)), .ordinal = htobe32(TPM2_CC_Startup), }, .startup_type = htobe16(startup_type), }; return talk(&ts, sizeof(ts), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TPM2_IncrementalSelfTest(int *tpm_errcode) { struct tpm2_incremental_selftest ts = { .hdr = { .tag = htobe16(TPM2_ST_NO_SESSIONS), .length = htobe32(sizeof(ts)), .ordinal = htobe32(TPM2_CC_IncrementalSelfTest), }, .to_test = { .num_entries = htobe32(1), .algids = { htobe16(TPM2_ALG_SHA1), }, }, }; return talk(&ts, sizeof(ts), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int TPM2_HierarchyChangeAuth(int *tpm_errcode) { struct tpm2_hierarchy_change_auth thca = { .hdr = { .tag = htobe16(TPM2_ST_SESSIONS), .length = htobe32(sizeof(thca)), .ordinal = htobe32(TPM2_CC_HierarchyChangeAuth), }, .authhandle = htobe32(TPM2_RH_PLATFORM), .authblock_size = htobe32(sizeof(thca.authblock)), .authblock = { .handle = htobe32(TPM2_RS_PW), .nonce_size = htobe16(0), .cont = 1, .password_size = htobe16(0), }, .newauth = { .size = htobe16(sizeof(thca.newauth.buffer)), }, }; int fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { ssize_t n = read(fd, &thca.newauth.buffer, sizeof(thca.newauth.buffer)); close(fd); if (n != sizeof(thca.newauth.buffer)) { printf("Read of bytes from /dev/urandom failed"); if (n < 0) printf(": %s", strerror(errno)); printf("\n"); return -1; } } else { printf("Could not open /dev/urandom: %s\n", strerror(errno)); return -1; } return talk(&thca, sizeof(thca), tpm_errcode, TPM_DURATION_SHORT, NULL, 0); } static int tpm12_bios(int do_more, int contselftest, unsigned char startupparm, int unassert_pp, int ensure_activated) { int ret = 0; int tpm_errcode; int tpm_error = 0; unsigned short physical_presence; struct tpm_get_capability_permflags_res perm_flags; if (ret == 0) { if (0xff != startupparm) { ret = TPM_Startup(startupparm, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TPM_Startup(0x%02x) returned " "error code 0x%08x\n", startupparm, tpm_errcode); } } } /* Sends the TSC_PhysicalPresence command to turn on physicalPresenceCMDEnable */ if ((ret == 0) && do_more) { physical_presence = TPM_PHYSICAL_PRESENCE_CMD_ENABLE; ret = TSC_PhysicalPresence(physical_presence, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TSC_PhysicalPresence(CMD_ENABLE) " "returned error code 0x%08x\n", tpm_errcode); } } /* Sends the TSC_PhysicalPresence command to turn on physicalPresence */ if ((ret == 0) && do_more) { physical_presence = TPM_PHYSICAL_PRESENCE_PRESENT; ret = TSC_PhysicalPresence(physical_presence, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TSC_PhysicalPresence(PRESENT) " "returned error code 0x%08x\n", tpm_errcode); } } /* Determine the permanent flags */ if ((ret == 0) && do_more && ensure_activated) { ret = TPM_GetCapability_Subcap(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT, &perm_flags.hdr, sizeof(perm_flags), &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TPM_GetCapability() returned error " "code 0x%08x\n", tpm_errcode); } } /* Sends the TPM_Process_PhysicalEnable command to clear disabled */ if ((ret == 0) && do_more) { ret = TPM_PhysicalEnable(&tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TPM_PhysicalEnable returned error " "code 0x%08x\n", tpm_errcode); } } /* Sends the TPM_Process_PhysicalSetDeactivated command to clear deactivated */ if ((ret == 0) && do_more) { ret = TPM_PhysicalSetDeactivated(0, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TPM_PhysicalSetDeactivated returned " "error code 0x%08x\n", tpm_errcode); } if (ensure_activated) { /* activation will require resetting the TPM */ if (perm_flags.flags[TPM_PERM_FLAG_DEACTIVATED_IDX]) { ret = 0x81; printf("TPM requires a reset\n"); } } } if ((ret == 0) && contselftest) { ret = TPM_ContinueSelfTest(&tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TPM_ContinueSelfTest returned error " "code 0x%08x\n", tpm_errcode); } } /* Sends the TSC_PhysicalPresence command to turn on physicalPresenceCMDEnable */ if ((ret == 0) && unassert_pp) { physical_presence = TPM_PHYSICAL_PRESENCE_CMD_ENABLE; ret = TSC_PhysicalPresence(physical_presence, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TSC_PhysicalPresence(CMD_ENABLE) returned " "error code 0x%08x\n", tpm_errcode); } } /* Sends the TSC_PhysicalPresence command to unassert physical presence and lock it */ if ((ret == 0) && unassert_pp) { physical_presence = TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK; ret = TSC_PhysicalPresence(physical_presence, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; fprintf(stderr, "TSC_PhysicalPresence(NOT_PRESENT|LOCK) " "returned error code 0x%08x\n", tpm_errcode); } } if (!ret && tpm_error) ret = 0x80; return ret; } static int tpm2_bios(int do_more, int contselftest, unsigned char startupparm, int set_password) { int ret = 0; int tpm_errcode; int tpm_error = 0; if (ret == 0) { if (0xff != startupparm) { ret = TPM2_Startup(startupparm, &tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; printf("TPM2_Startup returned error code " "0x%08x\n", tpm_errcode); } } } if ((ret == 0) && contselftest) { ret = TPM2_IncrementalSelfTest(&tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; printf("TPM2_ImcrementalSelfTest returned error " "code 0x%08x\n", tpm_errcode); } } if ((ret == 0) && set_password) { ret = TPM2_HierarchyChangeAuth(&tpm_errcode); if (tpm_errcode != 0) { tpm_error = 1; printf("TPM2_HierarchyChangeAuth returned error " "code 0x%08x\n", tpm_errcode); } } if (!ret && tpm_error) ret = 0x80; return ret; } static void versioninfo(void) { printf( "TPM emulator BIOS emulator version %d.%d.%d, Copyright (c) 2015 IBM Corp.\n" ,SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); } static void print_usage(const char *prgname) { versioninfo(); printf( "\n" "%s [options]\n" "\n" "Runs TPM_Startup (unless -n), then (unless -o) sets PP, enable, activate \n" "and finally (using -u) gives up physical presence (PP)\n" "\n" "The following options are supported:\n" "\t--tpm-device use the given device; default is /dev/tpm0\n" "\t--tcp []:[] connect to TPM on given host and port;\n" "\t default host is 127.0.0.1, default port is %u\n" "\t--unix connect to TPM using UnixIO socket\n" "\t--tpm2 initialize a TPM2\n" "\t-c startup clear (default)\n" "\t-s startup state\n" "\t-d startup deactivate (no effect on TPM2)\n" "\t-n no startup\n" "\t-o startup only\n" "\t-cs run TPM_ContinueSelfTest on TPM1.2\n" "\t run TPM2_IncrementalSelfTest on TPM2\n" "\t-ea make sure that the TPM 1.2 is activated;\n" "\t terminate with exit code 129 if the TPM\n" "\t needs to be reset\n" "\t-u give up physical presence\n" "\t on TPM 2 set the platform hierarchy to a\n" "\t random password\n" "\t-v display version and exit\n" "\t-h display this help screen and exit\n" , prgname, DEFAULT_TCP_PORT); } int main(int argc, char *argv[]) { int ret = 0; int do_more = 1; int ensure_activated = 0; int contselftest = 0; unsigned char startupparm = 0x1; /* parameter for TPM_Startup(); */ unsigned char startupparm_tpm2 = 0x00; int unassert_pp = 0; int tpm2 = 0; static struct option long_options[] = { {"tpm-device", required_argument, NULL, 'D'}, {"tcp", required_argument, NULL, 'T'}, {"unix", required_argument, NULL, 'U'}, {"c", no_argument, NULL, 'c'}, {"d", no_argument, NULL, 'd'}, {"h", no_argument, NULL, 'h'}, {"v", no_argument, NULL, 'v'}, {"n", no_argument, NULL, 'n'}, {"s", no_argument, NULL, 's'}, {"o", no_argument, NULL, 'o'}, {"cs", no_argument, NULL, 'C'}, {"ea", no_argument, NULL, 'E'}, {"u", no_argument, NULL, 'u'}, {"tpm2", no_argument, NULL, '2'}, {NULL, 0, NULL, 0}, }; int opt, option_index = 0; #ifdef __NetBSD__ while ((opt = getopt_long(argc, argv, "D:T:U:cdhvnsoCEu2", long_options, &option_index)) != -1) { #else while ((opt = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { #endif switch (opt) { case 'D': tpm_device = strdup(optarg); if (!tpm_device) { fprintf(stderr, "Out of memory."); return EXIT_FAILURE; } break; case 'T': if (parse_tcp_optarg(optarg, &tcp_hostname, &tcp_port) < 0) { return EXIT_FAILURE; } break; case 'U': unix_path = strdup(optarg); if (!unix_path) { fprintf(stderr, "Out of memory.\n"); return EXIT_FAILURE; } break; case 'c': startupparm = TPM_ST_CLEAR; startupparm_tpm2 = TPM2_SU_CLEAR; do_more = 1; break; case 'd': startupparm = TPM_ST_DEACTIVATED; startupparm_tpm2 = 0xff; do_more = 0; break; case 'h': print_usage(argv[0]); return EXIT_SUCCESS; case 'n': startupparm = 0xff; startupparm_tpm2 = 0xff; do_more = 1; break; case 's': startupparm = TPM_ST_STATE; startupparm_tpm2 = TPM2_SU_STATE; do_more = 1; break; case 'o': do_more = 0; break; case 'C': contselftest = 1; break; case 'E': ensure_activated = 1; break; case 'u': unassert_pp = 1; break; case '2': tpm2 = 1; break; default: print_usage(argv[0]); return EXIT_FAILURE; } } if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { fprintf(stderr, "Could not install signal handler for SIGPIPE."); return EXIT_FAILURE; } if (tpm2) { ret = tpm2_bios(do_more, contselftest, startupparm_tpm2, unassert_pp); } else { ret = tpm12_bios(do_more, contselftest, startupparm, unassert_pp, ensure_activated); } return ret; } swtpm-0.6.3/src/swtpm_bios/tpm_bios.h000066400000000000000000000113401421141172300176270ustar00rootroot00000000000000/* * tpm_bios. -- Header file for tpm_bios.c * * Authors: Stefan Berger * * (c) Copyright IBM Corporation 2016. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SWTPM_BIOS_H #define _SWTPM_BIOS_H #include /* constants for TPM 1.2 */ #define TPM_TAG_RQU_COMMAND 0x00c1 #define TPM_ST_CLEAR 0x0001 #define TPM_ST_STATE 0x0002 #define TPM_ST_DEACTIVATED 0x0003 #define TPM_ORD_ContinueSelfTest 0x00000053 #define TPM_ORD_GetCapability 0x00000065 #define TPM_ORD_PhysicalEnable 0x0000006f #define TPM_ORD_PhysicalDisable 0x00000070 #define TPM_ORD_PhysicalSetDeactivated 0x00000072 #define TPM_ORD_Startup 0x00000099 #define TPM_ORD_PhysicalPresence 0x4000000a #define TPM_PHYSICAL_PRESENCE_PRESENT 0x0008 #define TPM_PHYSICAL_PRESENCE_LOCK 0x0004 #define TPM_PHYSICAL_PRESENCE_NOTPRESENT 0x0010 #define TPM_PHYSICAL_PRESENCE_CMD_ENABLE 0x0020 #define TPM_CAP_FLAG 0x00000004 #define TPM_CAP_FLAG_PERMANENT 0x00000108 #define TPM_PERM_FLAG_DEACTIVATED_IDX 2 /* data structures for TPM 1.2 */ struct tpm_header { uint16_t tag; uint32_t length; uint32_t ordinal; } __attribute__((packed)); struct tpm_resp_header { uint16_t tag; uint32_t length; uint32_t result; } __attribute__((packed)); struct tpm_startup { struct tpm_header hdr; uint16_t startup_type; } __attribute__((packed)); struct tsc_physical_presence { struct tpm_header hdr; uint16_t physical_presence; } __attribute__((packed)); struct tpm_physical_enable { struct tpm_header hdr; } __attribute__((packed)); struct tpm_physical_set_deactivated { struct tpm_header hdr; uint8_t state; } __attribute__((packed)); struct tpm_continue_selftest { struct tpm_header hdr; } __attribute__((packed)); struct tpm_get_capability_subcap { struct tpm_header hdr; uint32_t cap; uint32_t subcap_size; uint32_t subcap; } __attribute__((packed)); struct tpm_get_capability_permflags_res { struct tpm_resp_header hdr; uint32_t size; uint16_t tag; uint8_t flags[20]; } __attribute__((packed)); /* constants for TPM 2 */ #define TPM2_ST_NO_SESSIONS 0x8001 #define TPM2_ST_SESSIONS 0x8002 #define TPM2_CC_HierarchyChangeAuth 0x00000129 #define TPM2_CC_IncrementalSelfTest 0x00000142 #define TPM2_CC_Startup 0x00000144 #define TPM2_SU_CLEAR 0x0000 #define TPM2_SU_STATE 0x0001 #define TPM2_ALG_SHA1 0x0004 #define TPM2_RS_PW 0x40000009 #define TPM2_RH_PLATFORM 0x4000000c /* data structures for TPM 2 */ struct tpm2_startup { struct tpm_header hdr; uint16_t startup_type; } __attribute__((packed)); struct tpm2l_alg_1_entry { uint32_t num_entries; uint16_t algids[1]; } __attribute__((packed)); struct tpm2_incremental_selftest { struct tpm_header hdr; struct tpm2l_alg_1_entry to_test; } __attribute__((packed)); struct tpm2_authblock { uint32_t handle; uint16_t nonce_size; uint8_t cont; uint16_t password_size; } __attribute__((packed)); struct tpm2b_20 { uint16_t size; uint8_t buffer[20]; } __attribute__((packed)); struct tpm2_hierarchy_change_auth { struct tpm_header hdr; uint32_t authhandle; uint32_t authblock_size; struct tpm2_authblock authblock; struct tpm2b_20 newauth; } __attribute__((packed)); #endif /* _SWTPM_BIOS_H */ swtpm-0.6.3/src/swtpm_cert/000077500000000000000000000000001421141172300156445ustar00rootroot00000000000000swtpm-0.6.3/src/swtpm_cert/Makefile.am000066400000000000000000000012111421141172300176730ustar00rootroot00000000000000# # src/swtpm_cert/Makefile.am # # For the license, see the LICENSE file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = bin_PROGRAMS = if WITH_GNUTLS bin_PROGRAMS += \ swtpm_cert endif swtpm_cert_SOURCES = \ ek-cert.c swtpm_cert_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ $(MY_CFLAGS) \ $(CFLAGS) swtpm_cert_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) ek-cert.o : tpm_asn1.h swtpm_cert_LDADD = \ $(LIBTASN1_LIBS) \ $(GNUTLS_LIBS) tpm_asn1.h : tpm.asn asn1Parser -o $@ $^ EXTRA_DIST = \ tpm.asn \ tpm_asn1.h \ README CLEANFILES = *.gcno *.gcda *.gcov swtpm-0.6.3/src/swtpm_cert/README000066400000000000000000000003761421141172300165320ustar00rootroot00000000000000swtpm_cert is a tool that creates EK and platform certificates for a TPM. It does not require a certificate request to be self signed but works only with the public key parameters of the EK. For further information, check the manpage 'man swtpm_cert'. swtpm-0.6.3/src/swtpm_cert/ek-cert.c000066400000000000000000001600231421141172300173440ustar00rootroot00000000000000/* * ek-cert.c * * Authors: Stefan Berger * * (c) Copyright IBM Corporation 2014, 2015, 2020. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Note: The construction of the certificate follows the TCG Credential * Profile for TPM Family 1.2; Level 2 Unified Trust Certificate * in section 3.5 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sys_dependencies.h" #include "tpm_asn1.h" #include "swtpm.h" enum cert_type_t { CERT_TYPE_EK = 1, CERT_TYPE_PLATFORM, CERT_TYPE_AIK, }; /* some flags */ #define CERT_TYPE_TPM2_F 1 #define ALLOW_SIGNING_F 2 /* EK can be used for signing */ #define DECRYPTION_F 4 /* EK can be used for decryption; default */ extern const asn1_static_node tpm_asn1_tab[]; asn1_node _tpm_asn; typedef struct tdTCG_PCCLIENT_STORED_CERT { uint16_t tag; uint8_t certType; uint16_t certSize; } __attribute__((packed)) tdTCG_PCCLIENT_STORED_CERT; typedef struct TCG_PCCLIENT_STORED_FULL_CERT_HEADER { tdTCG_PCCLIENT_STORED_CERT stored_cert; uint16_t tag; } __attribute__((packed)) TCG_PCCLIENT_STORED_FULL_CERT_HEADER; #define TCG_TAG_PCCLIENT_STORED_CERT 0x1001 #define TCG_TAG_PCCLIENT_FULL_CERT 0x1002 static void versioninfo(const char *prg) { fprintf(stdout, "TPM certificate tool version %d.%d.%d, Copyright (c) 2015 IBM Corp.\n" ,SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); } static void usage(const char *prg) { versioninfo(prg); fprintf(stdout, "\nUsage: %s [options]\n" "\n" "Create TPM certificates without requiring the EK private key.\n" "\n" "The following options are supported:\n" "--pubkey : PEM file for public key (EK)\n" "--signkey : PEM file for CA signing key or GnuTLS TPM or\n" " PKCS11 URL\n" "--signkey-password : Password for the CA signing key\n" "--signkey-pwd : Alternative password option for CA signing key\n" "--parentkey-password

: Password of parent key; SRK password of TPM\n" "--parentkey-pwd : Alternative password option for SRK password\n" "--issuercert : PEM file with CA cert\n" "--out-cert : Filename for certificate\n" "--modulus : The modulus of the public key\n" "--exponent : The exponent of the public key\n" "--ecc-x : ECC key x component\n" "--ecc-y : ECC key y component\n" "--ecc-curveid : ECC curve id; secp256r1, secp384r1, secp521r1\n" " default: secp256r1\n" "--serial : The certificate serial number\n" "--days : Number of days the cert is valid\n" "--pem : Write certificate in PEM format; default is DER\n" "--type : The type of certificate to create; default is ek\n" "--tpm-manufacturer : The name of the TPM manufacturer\n" "--tpm-model : The TPM model (part number)\n" "--tpm-version : The TPM version (firmware version)\n" "--platform-manufacturer : The name of the Platform manufacturer\n" "--platform-model : The Platform model (part number)\n" "--platform-version : The Platform version (firmware version)\n" "--tpm-spec-family : Specification family (string)\n" "--tpm-spec-level : Specification level (integer)\n" "--tpm-spec-revision : Specification revision (integer)\n" "--subject : Subject such as location in format\n" " C=US,ST=NY,L=NewYork; not used with TPM1.2\n" "--add-header : Add the TCG certificate header describing\n" " a TCG_PCCLIENT_STORED_CERT for TPM1.2 NVRAM\n" "--tpm2 : Issue a TPM 2 compliant certificate\n" "--allow-signing : The EK of a TPM 2 allows signing;\n" " requires --tpm2\n" "--decryption : The EK if a TPM 2 can be used for key\n" " encipherment; requires --tpm2\n" "--print-capabilities : Print capabilities and exit\n" "--version : Display version and exit\n" "--help : Display this help screen and exit\n" "\n" "The following environment variables are supported:\n" "\n" "SWTPM_PKCS11_PIN : PKCS11 PIN to use\n" "\n" "Password passed in 'pwd' options support the following formats:\n" "- : direct password\n" "- pass: : direct password\n" "- fd: : read password from file descriptor\n" "- file: : read password from filename\n" "- env: : read from environment variable\n" , prg); } static char hex_to_str(char digit) { char value = -1; if (digit >= '0' && digit <= '9') { value = digit - '0'; } else if (digit >= 'a' && digit <= 'f') { value = digit - 'a' + 10; } else if (digit >= 'A' && digit <= 'F') { value = digit - 'A' + 10; } return value; } static unsigned char * hex_str_to_bin(const char *hexstr, int *modulus_len) { int len; unsigned char *result; int i = 0, j = 0; char val1, val2; len = strlen(hexstr); if ((len & 1) != 0) { fprintf(stderr, "Got an odd number of hex digits (%d).\n", len); fprintf(stderr, " hex digits: %s\n", hexstr); return NULL; } result = malloc(len / 2); i = 0; j = 0; while (i < len) { val1 = hex_to_str(hexstr[i]); if (val1 < 0) { fprintf(stderr, "Illegal hex character '%c'.", hexstr[i]); free(result); return NULL; } i++; val2 = hex_to_str(hexstr[i]); if (val2 < 0) { fprintf(stderr, "Illegal hex character '%c'.", hexstr[i]); free(result); return NULL; } i++; result[j++] = (val1 << 4) | val2; } *modulus_len = j; return result; } static gnutls_pubkey_t create_rsa_from_modulus(unsigned char *modulus, unsigned int modulus_len, uint32_t exponent) { unsigned char exp_array[4]; uint32_t exponent_no = htonl(exponent); gnutls_pubkey_t rsa = NULL; gnutls_datum_t mod; gnutls_datum_t exp = { .data = exp_array, .size = sizeof(exp_array), }; int err; memcpy(exp_array, &exponent_no, sizeof(exp_array)); err = gnutls_pubkey_init(&rsa); if (err < 0) { fprintf(stderr, "Could not initialized public key structure : %s\n", gnutls_strerror(err)); return NULL; } mod.data = modulus; mod.size = modulus_len; err = gnutls_pubkey_import_rsa_raw(rsa, &mod, &exp); if (err < 0) { fprintf(stderr, "Could not set modulus and exponent on RSA key : %s\n", gnutls_strerror(err)); gnutls_pubkey_deinit(rsa); rsa = NULL; } return rsa; } static gnutls_pubkey_t create_ecc_from_x_and_y(unsigned char *ecc_x, unsigned int ecc_x_len, unsigned char *ecc_y, unsigned int ecc_y_len, const char *ecc_curveid) { gnutls_pubkey_t rsa = NULL; int err; gnutls_datum_t x = { .data = ecc_x, .size = ecc_x_len, }; gnutls_datum_t y = { .data = ecc_y, .size = ecc_y_len, }; gnutls_ecc_curve_t curve; err = gnutls_pubkey_init(&rsa); if (err < 0) { fprintf(stderr, "Could not initialized public key structure : %s\n", gnutls_strerror(err)); return NULL; } if (ecc_curveid == NULL || !strcmp(ecc_curveid, "secp256r1")) { curve = GNUTLS_ECC_CURVE_SECP256R1; } else if (!strcmp(ecc_curveid, "secp384r1")) { curve = GNUTLS_ECC_CURVE_SECP384R1; } else if (!strcmp(ecc_curveid, "secp521r1")) { curve = GNUTLS_ECC_CURVE_SECP521R1; } else { fprintf(stderr, "Unsupported ECC curve id: %s\n", ecc_curveid); return NULL; } err = gnutls_pubkey_import_ecc_raw(rsa, curve, &x, &y); if (err < 0) { fprintf(stderr, "Could not set x and y on ECC key : %s\n", gnutls_strerror(err)); gnutls_pubkey_deinit(rsa); rsa = NULL; } return rsa; } static int asn_init() { static bool inited; int err; if (inited) return ASN1_SUCCESS; err = asn1_array2tree(tpm_asn1_tab, &_tpm_asn, NULL); if (err != ASN1_SUCCESS) { fprintf(stderr, "array2tree error: %d", err); goto cleanup; } inited = true; cleanup: return err; } static void asn_free(void) { if (_tpm_asn) asn1_delete_structure(&_tpm_asn); } static int encode_asn1(gnutls_datum_t *asn1, asn1_node at) { int err; /* determine needed size of byte array */ asn1->size = 0; err = asn1_der_coding(at, "", NULL, (int *)&asn1->size, NULL); if (err != ASN1_MEM_ERROR) { fprintf(stderr, "1. asn1_der_coding error: %d\n", err); return err; } asn1->data = gnutls_malloc(asn1->size + 16); if (!asn1->data) { fprintf(stderr, "2. Could not allocate memory\n"); return ASN1_MEM_ERROR; } err = asn1_der_coding(at, "", asn1->data, (int *)&asn1->size, NULL); if (err != ASN1_SUCCESS) { fprintf(stderr, "3. asn1_der_coding error: %d\n", err); gnutls_free(asn1->data); asn1->data = NULL; } return err; } static int build_tpm_manufacturer_info(asn1_node *at, const char *manufacturer, const char *tpm_model, const char *tpm_version) { int err; err = asn1_create_element(_tpm_asn, "TPM.TPMManufacturerInfo", at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmManufacturerSet.tpmManufacturer.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "1a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmManufacturerSet.tpmManufacturer.id", "2.23.133.2.1", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "1b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmManufacturerSet.tpmManufacturer.manufacturer", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "2. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmModelSet.tpmModel.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "3a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmModelSet.tpmModel.id", "2.23.133.2.2", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "3b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmModelSet.tpmModel.model", tpm_model, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "4. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmVersionSet.tpmVersion.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "5a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmVersionSet.tpmVersion.id", "2.23.133.2.3", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "5b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "tpmVersionSet.tpmVersion.version", tpm_version, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "6. asn1_write_value error: %d\n", err); goto cleanup; } cleanup: return err; } static int create_tpm_manufacturer_info(const char *manufacturer, const char *tpm_model, const char *tpm_version, gnutls_datum_t *asn1) { asn1_node at = NULL; int err; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = build_tpm_manufacturer_info(&at, manufacturer, tpm_model, tpm_version); if (err != ASN1_SUCCESS) { goto cleanup; } err = encode_asn1(asn1, at); #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; } static int build_platf_manufacturer_info(asn1_node *at, const char *manufacturer, const char *platf_model, const char *platf_version, bool forTPM2) { int err; err = asn1_create_element(_tpm_asn, "TPM.PlatformManufacturerInfo", at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformManufacturerSet.platformManufacturer.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b1a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformManufacturerSet.platformManufacturer.id", forTPM2 ? "2.23.133.5.1.1" : "2.23.133.2.4", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b1b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformManufacturerSet.platformManufacturer.manufacturer", manufacturer, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b2. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformModelSet.platformModel.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b3a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformModelSet.platformModel.id", forTPM2 ? "2.23.133.5.1.4" : "2.23.133.2.5", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b3b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformModelSet.platformModel.model", platf_model, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b4. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformVersionSet.platformVersion.?LAST", "NEW", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b5a. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformVersionSet.platformVersion.id", forTPM2 ? "2.23.133.5.1.5" : "2.23.133.2.6", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b5b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(*at, "platformVersionSet.platformVersion.version", platf_version, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "b6. asn1_write_value error: %d\n", err); goto cleanup; } cleanup: return err; } static int create_platf_manufacturer_info(const char *manufacturer, const char *platf_model, const char *platf_version, gnutls_datum_t *asn1, bool forTPM2) { asn1_node at = NULL; int err; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = build_platf_manufacturer_info(&at, manufacturer, platf_model, platf_version, forTPM2); if (err != ASN1_SUCCESS) { goto cleanup; } err = encode_asn1(asn1, at); #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; } static int create_tpm_and_platform_manuf_info( const char *tpm_manufacturer, const char *tpm_model, const char *tpm_version, const char *platf_manufacturer, const char *platf_model, const char *platf_version, gnutls_datum_t *asn1, bool forTPM2) { asn1_node at = NULL; asn1_node tpm_at = NULL; asn1_node platf_at = NULL; int err; gnutls_datum_t datum = { .data = NULL, .size = 0, }; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = asn1_create_element(_tpm_asn, "TPM.PlatformCertificateSAN", &at); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: asn1_create_element error: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } /* build the TPM manufacturer data */ err = build_tpm_manufacturer_info(&tpm_at, tpm_manufacturer, tpm_model, tpm_version); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not build TPM manufacturer info: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = encode_asn1(&datum, tpm_at); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not encode TPM data as ASN.1: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = asn1_write_value(at, "", "NEW", 1); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not create a NEW element: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = asn1_write_value(at, "?1", datum.data, datum.size); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not write 1st element: %s!\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } gnutls_free(datum.data); datum.data = NULL; /* build the platform manufacturer data */ err = build_platf_manufacturer_info(&platf_at, platf_manufacturer, platf_model, platf_version, forTPM2); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not build platform manufacturer info: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = encode_asn1(&datum, platf_at); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not encode platform data as ASN.1: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = asn1_write_value(at, "", "NEW", 1); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not create a NEW element: %s\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } err = asn1_write_value(at, "?2", datum.data, datum.size); if (err != ASN1_SUCCESS) { fprintf(stderr, "%s: %d: Could not write 2nd element: %s!\n", __func__, __LINE__, asn1_strerror(err)); goto cleanup; } gnutls_free(datum.data); datum.data = NULL; err = encode_asn1(asn1, at); #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: gnutls_free(datum.data); asn1_delete_structure(&at); asn1_delete_structure(&platf_at); asn1_delete_structure(&tpm_at); return err; } static int create_tpm_specification_info(const char *spec_family, unsigned int spec_level, unsigned int spec_revision, gnutls_datum_t *asn1) { asn1_node at = NULL; int err; unsigned int bigendian; unsigned char twoscomp[1 + sizeof(bigendian)] = { 0, }; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = asn1_create_element(_tpm_asn, "TPM.TPMSpecificationInfo", &at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmSpecificationSeq.id", "2.23.133.2.16", 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "c1b. asn1_write_value error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "tpmSpecificationSeq.tpmSpecificationSet.tpmSpecification.family", spec_family, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "c1c. asn1_write_value error: %d\n", err); goto cleanup; } bigendian = htobe32(spec_level); memcpy(&twoscomp[1], &bigendian, sizeof(bigendian)); err = asn1_write_value(at, "tpmSpecificationSeq.tpmSpecificationSet.tpmSpecification.level", twoscomp, sizeof(twoscomp)); if (err != ASN1_SUCCESS) { fprintf(stderr, "c1d. asn1_write_value error: %d\n", err); goto cleanup; } bigendian = htobe32(spec_revision); memcpy(&twoscomp[1], &bigendian, sizeof(bigendian)); err = asn1_write_value(at, "tpmSpecificationSeq.tpmSpecificationSet.tpmSpecification.revision", twoscomp, sizeof(twoscomp)); if (err != ASN1_SUCCESS) { fprintf(stderr, "c1e. asn1_write_value error: %d\n", err); goto cleanup; } err = encode_asn1(asn1, at); #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; } static int create_cert_extended_key_usage(const char *oid, gnutls_datum_t *asn1) { asn1_node at = NULL; int err; err = asn_init(); if (err != ASN1_SUCCESS) { goto cleanup; } err = asn1_create_element(_tpm_asn, "TPM.TPMEKCertExtendedKeyUsage", &at); if (err != ASN1_SUCCESS) { fprintf(stderr, "asn1_create_element error: %d\n", err); goto cleanup; } err = asn1_write_value(at, "id", oid, 0); if (err != ASN1_SUCCESS) { fprintf(stderr, "d1. asn1_write_value error: %d\n", err); goto cleanup; } err = encode_asn1(asn1, at); #if 0 fprintf(stderr, "size=%d\n", asn1->size); unsigned int i = 0; for (i = 0; i < asn1->size; i++) { fprintf(stderr, "%02x ", asn1->data[i]); } fprintf(stderr, "\n"); #endif cleanup: asn1_delete_structure(&at); return err; } /* * prepend_san_asn1_header -- prepend a SAN ASN.1 header on the data * * This function with prepend something like this: * 0x30 0xa4 */ static int prepend_san_asn1_header(gnutls_datum_t *datum) { int err = GNUTLS_E_SUCCESS; unsigned char buffer[2 * (1 + 1 + sizeof(unsigned long))]; unsigned i = sizeof(buffer); unsigned long size; unsigned char intlen; unsigned char *data = datum->data; /* write backwards */ intlen = 0; size = datum->size; do { buffer[--i] = (size & 0xff); size >>= 8; intlen++; } while (size); /* * short form for values 0x00 .. 0x7f * long form for anything larger */ if (intlen > 1 || buffer[i] & 0x80) buffer[--i] = intlen | 0x80; /* write equivalent of 0xa4 */ buffer[--i] = ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_CLASS_STRUCTURED | ASN1_TAG_OCTET_STRING; size = datum->size + sizeof(buffer) - i; intlen = 0; do { buffer[--i] = (size & 0xff); size >>= 8; intlen++; } while (size); if (intlen > 1 || buffer[i] & 0x80) buffer[--i] = intlen | 0x80; /* write equivalent of 0x30 */ buffer[--i] = ASN1_CLASS_STRUCTURED | ASN1_TAG_SEQUENCE; datum->data = gnutls_malloc(datum->size + sizeof(buffer) - i); if (datum->data == NULL) { err = GNUTLS_E_MEMORY_ERROR; goto exit; } memcpy(datum->data, &buffer[i], sizeof(buffer) - i); memcpy(&datum->data[sizeof(buffer) - i], data, datum->size); datum->size = sizeof(buffer) - i + datum->size; exit: gnutls_free(data); return err; } static int mypinfunc(void *userdata, int attempt, const char *tokenurl, const char *token_label, unsigned int flags, char *pin, size_t pin_max) { const char *userpin = getenv("SWTPM_PKCS11_PIN"); if (!userpin) return -1; strncpy(pin, userpin, pin_max - 1); pin[pin_max - 1] = 0; return 0; } /* * Get the password from the password parameter, which may have one of the * following formats: * * pass: * fd: * file: * env: * Any password read from files must not exceed 256 bytes including * teminating 0 byte. */ static char *get_password(const char *password) { char *result; char *endptr; int fd; char buffer[256]; ssize_t n; const char *tocopy; if (!strncmp(password, "fd:", 3)) { errno = 0; fd = strtol(&password[3], &endptr, 10); if (errno != 0 || fd < 0 || endptr == &password[3] || *endptr != 0) { fprintf(stderr, "Bad file descriptor for password.\n"); return NULL; } goto readfd; } else if (!strncmp(password, "file:", 5)) { fd = open(&password[5], O_RDONLY); if (fd < 0) { fprintf(stderr, "Could not open password file for reading: %s\n", strerror(errno)); return NULL; } readfd: n = read(fd, buffer, sizeof(buffer) - 1); close(fd); if (n < 0) { fprintf(stderr, "Could not read password from file descriptor: %s\n", strerror(errno)); return NULL; } buffer[n] = 0; tocopy = buffer; } else if (!strncmp(password, "pass:", 5)) { tocopy = &password[5]; } else if (!strncmp(password, "env:", 4)) { tocopy = getenv(&password[4]); if (tocopy == NULL) { fprintf(stderr, "Could not get password from environment variable\n"); return NULL; } } else { tocopy = password; } result = strdup(tocopy); if (!result) fprintf(stderr, "Out of memory.\n"); return result; } static void capabilities_print_json() { fprintf(stdout, "{ " "\"type\": \"swtpm_cert\", " "\"features\": [ " "\"cmdarg-signkey-pwd\"" ", \"cmdarg-parentkey-pwd\"" " ] " "}\n"); } int main(int argc, char *argv[]) { int ret = 1; gnutls_pubkey_t pubkey = NULL; gnutls_x509_privkey_t sigkey = NULL; gnutls_x509_crt_t sigcert = NULL; gnutls_x509_crt_t crt = NULL; gnutls_privkey_t tpmkey = NULL, pkcs11key = NULL; const char *pubkey_filename = NULL; const char *sigkey_filename = NULL; const char *cert_filename = NULL; const char *issuercert_filename = NULL; unsigned char *modulus_bin = NULL; int modulus_len = 0; unsigned char *ecc_x_bin = NULL; int ecc_x_len = 0; unsigned char *ecc_y_bin = NULL; int ecc_y_len = 0; const char *ecc_curveid = NULL; gnutls_datum_t datum = { NULL, 0}, out = { NULL, 0}; gnutls_digest_algorithm_t hashAlgo = GNUTLS_DIG_SHA1; unsigned long long serial = 1; time_t now; int err; int cert_file_fd; const char *subject = NULL; const char *error = NULL; int days = 365; char *sigkeypass = NULL; char *parentkeypass = NULL; uint64_t ser_number; long int exponent = 0x10001; bool write_pem = false; uint8_t id[512]; size_t id_size = sizeof(id); enum cert_type_t certtype = CERT_TYPE_EK; const char *oid; unsigned int key_usage = 0; const char *tpm_manufacturer = NULL; const char *tpm_version = NULL; const char *tpm_model = NULL; const char *platf_manufacturer = NULL; const char *platf_version = NULL; const char *platf_model = NULL; bool add_header = false; const char *spec_family = NULL; long int spec_level = ~0; long int spec_revision = ~0; int flags = 0; bool is_ecc = false; static struct option long_options[] = { {"pubkey", required_argument, NULL, 'p'}, {"modulus", required_argument, NULL, 'm'}, {"ecc-x", required_argument, NULL, 'x'}, {"ecc-y", required_argument, NULL, 'y'}, {"ecc-curveid", required_argument, NULL, 'z'}, {"exponent", required_argument, NULL, 'e'}, {"signkey", required_argument, NULL, 's'}, {"signkey-password", required_argument, NULL, 'S'}, {"signkey-pwd", required_argument, NULL, 'T'}, {"parentkey-passord", required_argument, NULL, 'P'}, {"parentkey-pwd", required_argument, NULL, 'Q'}, {"issuercert", required_argument, NULL, 'i'}, {"out-cert", required_argument, NULL, 'o'}, {"subject", required_argument, NULL, 'u'}, {"days", required_argument, NULL, 'd'}, {"serial", required_argument, NULL, 'r'}, {"type", required_argument, NULL, 't'}, {"tpm-manufacturer", required_argument, NULL, '1'}, {"tpm-model", required_argument, NULL, '2'}, {"tpm-version", required_argument, NULL, '3'}, {"platform-manufacturer", required_argument, NULL, '4'}, {"platform-model", required_argument, NULL, '5'}, {"platform-version", required_argument, NULL, '6'}, {"tpm-spec-family", required_argument, NULL, '7'}, {"tpm-spec-level", required_argument, NULL, '8'}, {"tpm-spec-revision", required_argument, NULL, '9'}, {"pem", no_argument, NULL, 'M'}, {"add-header", no_argument, NULL, 'a'}, {"tpm2", no_argument, NULL, 'X'}, {"allow-signing", no_argument, NULL, 'A'}, {"decryption", no_argument, NULL, 'D'}, {"print-capabilities", no_argument, NULL, 'c'}, {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; int opt, option_index = 0; char *endptr; #ifdef __NetBSD__ while ((opt = getopt_long(argc, argv, "p:m:x:y:z:e:s:S:T:P:Q:i:o:u:d:r:1:2:3:4:5:6:7:8:9:MaXADcvh", long_options, &option_index)) != -1) { #else while ((opt = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { #endif switch (opt) { case 'p': /* --pubkey */ pubkey_filename = optarg; break; case 'm': /* --modulus */ if (!(modulus_bin = hex_str_to_bin(optarg, &modulus_len))) { goto cleanup; } break; case 'x': /* --ecc-x */ if (!(ecc_x_bin = hex_str_to_bin(optarg, &ecc_x_len))) { goto cleanup; } break; case 'y': /* --ecc-y */ if (!(ecc_y_bin = hex_str_to_bin(optarg, &ecc_y_len))) { goto cleanup; } break; case 'z': /* --ecc-curveid */ ecc_curveid = optarg; break; case 'e': /* --exponent */ exponent = strtol(optarg, NULL, 0); if (exponent == 0) { fprintf(stderr, "Exponent is wrong and cannot be 0.\n"); goto cleanup; } if ((unsigned long int)exponent > UINT_MAX) { fprintf(stderr, "Exponent must fit into 32bits.\n"); goto cleanup; } break; case 's': /* --signkey */ sigkey_filename = optarg; break; case 'S': /* --signkey-password */ free(sigkeypass); sigkeypass = strdup(optarg); if (!sigkeypass) { fprintf(stderr, "Out of memory.\n"); goto cleanup; } break; case 'T': /* --signkey-pwd */ free(sigkeypass); sigkeypass = get_password(optarg); if (!sigkeypass) goto cleanup; break; case 'P': /* --parentkey-password */ free(parentkeypass); parentkeypass = strdup(optarg); if (!parentkeypass) { fprintf(stderr, "Out of memory.\n"); goto cleanup; } break; case 'Q': /* --parentkey-pwd */ free(parentkeypass); parentkeypass = get_password(optarg); if (!parentkeypass) goto cleanup; break; case 'i': /* --issuercert */ issuercert_filename = optarg; break; case 'o': /* --out-cert */ cert_filename = optarg; break; case 'u': /* --subject */ subject = optarg; break; case 'd': /* --days */ days = atoi(optarg); if (days < 0) { fprintf(stderr, "Days must be a positive number.\n"); goto cleanup; } break; case 'r': /* --serial */ errno = 0; serial = strtoull(optarg, &endptr, 10); if (errno != 0 || optarg == endptr || *endptr != 0) { fprintf(stderr, "Serial number is invalid.\n"); goto cleanup; } break; case 't': /* --type */ if (!strcasecmp(optarg, "ek")) { certtype = CERT_TYPE_EK; } else if (!strcasecmp(optarg, "platform")) { certtype = CERT_TYPE_PLATFORM; } else { fprintf(stderr, "Unknown certificate type '%s'.\n", optarg); goto cleanup; } break; case '1': /* --tpm-manufacturer */ tpm_manufacturer = optarg; break; case '2': /* --tpm-model */ tpm_model = optarg; break; case '3': /* --tpm-version */ tpm_version = optarg; break; case '4': /* --platform-manufacturer */ platf_manufacturer = optarg; break; case '5': /* --platform-model */ platf_model = optarg; break; case '6': /* --platform-version */ platf_version = optarg; break; case '7': /* --tpm-spec-family */ spec_family = optarg; break; case '8': /* --tpm-spec-level */ spec_level = strtol(optarg, NULL, 0); if (spec_level < 0) { fprintf(stderr, "--tpm-spec-level must pass a positive number.\n"); goto cleanup; } break; case '9': /* --tpm-spec-revision */ spec_revision = strtol(optarg, NULL, 0); if (spec_revision < 0) { fprintf(stderr, "--tpm-spec-revision must pass a positive number.\n"); goto cleanup; } break; case 'M': /* --pem */ write_pem = true; break; case 'a': /* --add-header */ add_header = true; break; case 'X': /* --tpm2 */ flags |= CERT_TYPE_TPM2_F; break; case 'A': /* --allow-signing */ flags |= ALLOW_SIGNING_F; break; case 'D': /* --decryption */ flags |= DECRYPTION_F; break; case 'c': /* --print-capabilities */ capabilities_print_json(); exit(0); case 'v': /* --version */ versioninfo(argv[0]); exit(0); case 'h': /* --help */ usage(argv[0]); exit(0); default: usage(argv[0]); exit(1); } } if (flags & CERT_TYPE_TPM2_F) hashAlgo = GNUTLS_DIG_SHA256; ser_number = htobe64(serial); if (modulus_bin && (ecc_x_bin || ecc_y_bin)) { fprintf(stderr, "RSA modulus and ECC parameters cannot both be " "given.\n"); goto cleanup; } if ((ecc_x_bin && !ecc_y_bin) || (ecc_y_bin && !ecc_x_bin)) { fprintf(stderr, "ECC x and y parameters must both be given.\n"); goto cleanup; } if (pubkey_filename == NULL && !modulus_bin && !ecc_x_bin) { fprintf(stderr, "Missing public EK file and modulus or ECC " "parameters.\n"); usage(argv[0]); goto cleanup; } if (issuercert_filename == NULL) { fprintf(stderr, "The issuer certificate name is required.\n"); goto cleanup; } switch (certtype) { case CERT_TYPE_EK: case CERT_TYPE_PLATFORM: if (tpm_manufacturer == NULL || tpm_model == NULL || tpm_version == NULL) { fprintf(stderr, "--tpm-manufacturer and --tpm-model and " "--tpm version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_AIK: break; } switch (certtype) { case CERT_TYPE_PLATFORM: if (platf_manufacturer == NULL || platf_model == NULL || platf_version == NULL) { fprintf(stderr, "--platform-manufacturer and --platform-model and " "--platform version " "must all be provided\n"); goto cleanup; } break; case CERT_TYPE_EK: if (spec_family == NULL || spec_level == ~0 || spec_revision == ~0) { fprintf(stderr, "--tpm-spec-family and --tpm-spec-level and " "--tpm-spec-revision must all be provided\n"); goto cleanup; } break; case CERT_TYPE_AIK: break; } err = gnutls_global_init(); if (err < 0) { fprintf(stderr, "gnutls_global_init failed.\n"); goto cleanup; } if (pubkey_filename) { gnutls_pubkey_init(&pubkey); err = gnutls_load_file(pubkey_filename, &datum); if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not open file for EK public key: %s\n", strerror(errno)); goto cleanup; } err = gnutls_pubkey_import(pubkey, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; if (err != GNUTLS_E_SUCCESS) { fprintf(stderr, "Could not import EK.\n"); goto cleanup; } } else { if (modulus_bin) { pubkey = create_rsa_from_modulus(modulus_bin, modulus_len, exponent); free(modulus_bin); modulus_bin = NULL; } else if (ecc_x_bin) { pubkey = create_ecc_from_x_and_y(ecc_x_bin, ecc_x_len, ecc_y_bin, ecc_y_len, ecc_curveid); free(ecc_x_bin); ecc_x_bin = NULL; free(ecc_y_bin); ecc_y_bin = NULL; is_ecc = true; } if (pubkey == NULL) goto cleanup; } /* all types of keys must have pubkey set now otherwise the signing will not work */ if (sigkey_filename == NULL) { fprintf(stderr, "Missing signature key.\n"); usage(argv[0]); exit(1); } #define CHECK_GNUTLS_ERROR(_err, _msg, ...) \ if (_err != GNUTLS_E_SUCCESS) { \ fprintf(stderr, _msg, __VA_ARGS__); \ goto cleanup; \ } if (strstr(sigkey_filename, "tpmkey:uuid=") == sigkey_filename || strstr(sigkey_filename, "tpmkey:file=") == sigkey_filename) { /* GnuTLS TPM 1.2 key URL */ err = gnutls_privkey_init(&tpmkey); CHECK_GNUTLS_ERROR(err, "Could not initialize tpmkey: %s\n", gnutls_strerror(err)); err = gnutls_privkey_import_tpm_url(tpmkey, sigkey_filename, parentkeypass, sigkeypass, 0); CHECK_GNUTLS_ERROR(err, "Could not import tpmkey %s: %s\n", sigkey_filename, gnutls_strerror(err)); } else if (strstr(sigkey_filename, "pkcs11:") == sigkey_filename) { gnutls_pkcs11_set_pin_function(mypinfunc, NULL); /* GnuTLS PKCS11 key URI */ err = gnutls_privkey_init(&pkcs11key); CHECK_GNUTLS_ERROR(err, "Could not initialize tpmkey: %s\n", gnutls_strerror(err)); err = gnutls_privkey_import_url(pkcs11key, sigkey_filename, 0); CHECK_GNUTLS_ERROR(err, "Could not import pkcs11 key %s: %s\n", sigkey_filename, gnutls_strerror(err)); } else { err = gnutls_x509_privkey_init(&sigkey); CHECK_GNUTLS_ERROR(err, "Could not initialize sigkey: %s\n", gnutls_strerror(err)); err = gnutls_load_file(sigkey_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read signing key from file %s: %s\n", sigkey_filename, gnutls_strerror(err)); if (sigkeypass) { err = gnutls_x509_privkey_import2(sigkey, &datum, GNUTLS_X509_FMT_PEM, sigkeypass, 0); } else { err = gnutls_x509_privkey_import(sigkey, &datum, GNUTLS_X509_FMT_PEM); } } gnutls_free(datum.data); datum.data = NULL; CHECK_GNUTLS_ERROR(err, "Could not import signing key : %s\n", gnutls_strerror(err)); err = gnutls_load_file(issuercert_filename, &datum); CHECK_GNUTLS_ERROR(err, "Could not read certificate from file %s : %s\n", issuercert_filename, gnutls_strerror(err)); gnutls_x509_crt_init(&sigcert); err = gnutls_x509_crt_import(sigcert, &datum, GNUTLS_X509_FMT_PEM); gnutls_free(datum.data); datum.data = NULL; datum.size = 0; CHECK_GNUTLS_ERROR(err, "Could not import issuer certificate: %s\n", gnutls_strerror(err)); err = gnutls_x509_crt_init(&crt); CHECK_GNUTLS_ERROR(err, "CRT init failed: %s\n", gnutls_strerror(err)) /* 3.5.1 Version */ err = gnutls_x509_crt_set_version(crt, 3); CHECK_GNUTLS_ERROR(err, "Could not set version on CRT: %s\n", gnutls_strerror(err)) /* 3.5.2 Serial Number */ err = gnutls_x509_crt_set_serial(crt, &ser_number, sizeof(ser_number)); CHECK_GNUTLS_ERROR(err, "Could not set serial on CRT: %s\n", gnutls_strerror(err)) /* 3.5.5 Validity */ now = time(NULL); err = gnutls_x509_crt_set_activation_time(crt, now); CHECK_GNUTLS_ERROR(err, "Could not set activation time on CRT: %s\n", gnutls_strerror(err)) err = gnutls_x509_crt_set_expiration_time(crt, now + (time_t)days * 24 * 60 * 60); CHECK_GNUTLS_ERROR(err, "Could not set expiration time on CRT: %s\n", gnutls_strerror(err)) /* 3.5.6 Subject -- must be empty for TPM 1.2 */ if (subject && (flags & CERT_TYPE_TPM2_F)) { err = gnutls_x509_crt_set_dn(crt, subject, &error); CHECK_GNUTLS_ERROR(err, "Could not set DN on CRT: %s\n" "DN '%s must be fault after %s\n.'", gnutls_strerror(err), subject, error) } /* 3.5.7 Public Key Info */ switch (certtype) { case CERT_TYPE_EK: oid = "1.2.840.113549.1.1.7"; break; case CERT_TYPE_PLATFORM: oid = NULL; break; case CERT_TYPE_AIK: oid = "1.2.840.113549.1.1.1"; break; default: fprintf(stderr, "Internal error: unhandle case in line %d\n", __LINE__); goto cleanup; } if (oid) { err = gnutls_x509_crt_set_key_purpose_oid(crt, oid, 0); CHECK_GNUTLS_ERROR(err, "Could not set key purpose on CRT: %s\n", gnutls_strerror(err)) } /* 3.5.8 Certificate Policies -- skip since not mandated */ /* 3.5.9 Subject Alternative Names */ switch (certtype) { case CERT_TYPE_EK: err = create_tpm_manufacturer_info(tpm_manufacturer, tpm_model, tpm_version, &datum); if (err) { fprintf(stderr, "Could not create TPM manufacturer info"); goto cleanup; } break; case CERT_TYPE_PLATFORM: if (flags & CERT_TYPE_TPM2_F) { err = create_platf_manufacturer_info(platf_manufacturer, platf_model, platf_version, &datum, true); if (err) { fprintf(stderr, "Could not create platform manufacturer " "info"); goto cleanup; } } else { err = create_tpm_and_platform_manuf_info(tpm_manufacturer, tpm_model, tpm_version, platf_manufacturer, platf_model, platf_version, &datum, false); if (err) { fprintf(stderr, "Could not create TPM and platform " "manufacturer info"); goto cleanup; } } break; case CERT_TYPE_AIK: break; default: fprintf(stderr, "Internal error: unhandle case in line %d\n", __LINE__); goto cleanup; } if (datum.size > 0) { err = prepend_san_asn1_header(&datum); CHECK_GNUTLS_ERROR(err, "Could not prepend SAN ASN.1 header: %s\n", gnutls_strerror(err)) err = gnutls_x509_crt_set_extension_by_oid(crt, GNUTLS_X509EXT_OID_SAN, datum.data, datum.size, 1); CHECK_GNUTLS_ERROR(err, "Could not set subject alt name: %s\n", gnutls_strerror(err)) } gnutls_free(datum.data); datum.data = NULL; datum.size = 0; /* 3.5.10 Basic Constraints */ err = gnutls_x509_crt_set_basic_constraints(crt, 0, -1); CHECK_GNUTLS_ERROR(err, "Could not set key usage id: %s\n", gnutls_strerror(err)) /* 3.5.11 Subject Directory Attributes */ switch (certtype) { case CERT_TYPE_EK: err = create_tpm_specification_info(spec_family, spec_level, spec_revision, &datum); if (err) { fprintf(stderr, "Could not create TPMSpecification\n"); goto cleanup; } break; case CERT_TYPE_PLATFORM: case CERT_TYPE_AIK: break; default: fprintf(stderr, "Internal error: unhandled case in line %d\n", __LINE__); goto cleanup; } if (!err && datum.size > 0) { err = gnutls_x509_crt_set_extension_by_oid(crt, "2.5.29.9", datum.data, datum.size, 0); CHECK_GNUTLS_ERROR(err, "Could not set subject directory attributes: " "%s\n", gnutls_strerror(err)) } gnutls_free(datum.data); datum.data = NULL; /* 3.5.12 Authority Key Id */ err = gnutls_x509_crt_get_subject_key_id(sigcert, id, &id_size, NULL); if (err == GNUTLS_E_SUCCESS && id_size > 0) { err = gnutls_x509_crt_set_authority_key_id(crt, id, id_size); CHECK_GNUTLS_ERROR(err, "Could not set the authority key id: %s\n", gnutls_strerror(err)) } else { CHECK_GNUTLS_ERROR(err, "Could not get the authority key id from the cert: %s\n", gnutls_strerror(err)) } /* 3.5.13 Authority Info Access -- may be omitted */ /* 3.5.14 CRL Distribution -- missing */ /* 3.5.15 Key Usage */ switch (certtype) { case CERT_TYPE_EK: case CERT_TYPE_PLATFORM: if (flags & CERT_TYPE_TPM2_F) { /* support 'User Device TPM' and 'Non-User Device TPM' in spec */ if (flags & ALLOW_SIGNING_F) { key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE; } if ((flags & (ALLOW_SIGNING_F | DECRYPTION_F)) == 0 || (flags & DECRYPTION_F) == DECRYPTION_F) { if (is_ecc) { key_usage |= GNUTLS_KEY_KEY_AGREEMENT; } else { key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT; } } } else { key_usage = GNUTLS_KEY_KEY_ENCIPHERMENT; } break; case CERT_TYPE_AIK: key_usage = GNUTLS_KEY_DIGITAL_SIGNATURE; break; default: fprintf(stderr, "Internal error: unhandle case in line %d\n", __LINE__); goto cleanup; } err = gnutls_x509_crt_set_key_usage(crt, key_usage); CHECK_GNUTLS_ERROR(err, "Could not set key usage id: %s\n", gnutls_strerror(err)) /* 3.5.16 Extended Key Usage */ oid = NULL; switch (certtype) { case CERT_TYPE_EK: oid = "2.23.133.8.1"; break; case CERT_TYPE_PLATFORM: oid = "2.23.133.8.2"; break; case CERT_TYPE_AIK: break; default: fprintf(stderr, "Internal error: unhandled case in line %d\n", __LINE__); goto cleanup; } if (oid) { err = create_cert_extended_key_usage(oid, &datum); if (err) { fprintf(stderr, "Could not create ASN.1 for extended key usage\n"); goto cleanup; } err = gnutls_x509_crt_set_extension_by_oid(crt, GNUTLS_X509EXT_OID_EXTENDED_KEY_USAGE, datum.data, datum.size, 0); CHECK_GNUTLS_ERROR(err, "Could not set extended key usage by oid: %s\n", gnutls_strerror(err)) gnutls_free(datum.data); datum.data = NULL; } /* 3.5.17 Subject Key Id -- should not be included */ /* 3.5.18 Issuer Alt. Name -- should not be included */ /* 3.5.19 FreshestCRL -- should not be included */ /* 3.5.20 Subject Info. Access -- should not be included */ /* 3.5.21 Subject and Issued Unique Ids -- must be omitted */ /* 3.5.22 Virtualized Platform Attestation Service -- missing */ /* 3.5.23 Migration Controller Attestation Service -- missing */ /* 3.5.24 Migration Controller Registration Service -- missing */ /* 3.5.25 Virtual Platform Backup Service -- missing */ /* set public key */ err = gnutls_x509_crt_set_pubkey(crt, pubkey); CHECK_GNUTLS_ERROR(err, "Could not set public EK on CRT: %s\n", gnutls_strerror(err)) /* sign cert */ if (sigkey) { err = gnutls_x509_crt_sign2(crt, sigcert, sigkey, hashAlgo, 0); } else if (pkcs11key) { err = gnutls_x509_crt_privkey_sign(crt, sigcert, pkcs11key, hashAlgo, 0); } else { /* TPM 1.2 signs cert for a TPM 1.2 (SHA1) or TPM 2 (SHA256) */ err = gnutls_x509_crt_privkey_sign(crt, sigcert, tpmkey, hashAlgo, 0); } CHECK_GNUTLS_ERROR(err, "Could not sign the CRT: %s [%s]\n", gnutls_strerror(err), sigkey_filename) /* write cert to file; either PEM or DER */ gnutls_x509_crt_export2(crt, (write_pem) ? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER, &out); if (cert_filename) { cert_file_fd = open(cert_filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOFOLLOW, S_IRUSR|S_IWUSR); if (cert_file_fd < 0) { fprintf(stderr, "Could not open %s for writing the certificate: %s\n", cert_filename, strerror(errno)); goto cleanup; } if (add_header) { TCG_PCCLIENT_STORED_FULL_CERT_HEADER hdr = { .stored_cert = { .tag = htobe16(TCG_TAG_PCCLIENT_STORED_CERT), .certType = 0, .certSize = htobe16(out.size + 2), }, .tag = htobe16(TCG_TAG_PCCLIENT_FULL_CERT), }; if (sizeof(hdr) != write(cert_file_fd, &hdr, sizeof(hdr))) { fprintf(stderr, "Could not write certificate header: %s\n", strerror(errno)); close(cert_file_fd); unlink(cert_filename); goto cleanup; } } if ((ssize_t)out.size != write(cert_file_fd, out.data, out.size)) { fprintf(stderr, "Could not write certificate into file: %s\n", strerror(errno)); close(cert_file_fd); unlink(cert_filename); goto cleanup; } close(cert_file_fd); } else { fprintf(stdout, "%s\n", out.data); } ret = 0; cleanup: gnutls_free(out.data); gnutls_x509_crt_deinit(crt); gnutls_x509_crt_deinit(sigcert); gnutls_x509_privkey_deinit(sigkey); gnutls_pubkey_deinit(pubkey); gnutls_privkey_deinit(tpmkey); gnutls_privkey_deinit(pkcs11key); gnutls_global_deinit(); free(sigkeypass); free(parentkeypass); free(modulus_bin); free(ecc_x_bin); free(ecc_y_bin); asn_free(); return ret; } swtpm-0.6.3/src/swtpm_cert/tpm.asn000066400000000000000000000045021421141172300171500ustar00rootroot00000000000000TPM { } DEFINITIONS IMPLICIT TAGS ::= BEGIN tcg OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) international-organizations(23) tcg(133) } tcg-attribute OBJECT IDENTIFIER ::= {tcg 2} tcg-at-tpmManufacturer OBJECT IDENTIFIER ::= {tcg-attribute 1} tcg-at-tpmModel OBJECT IDENTIFIER ::= {tcg-attribute 2} tcg-at-tpmVersion OBJECT IDENTIFIER ::= {tcg-attribute 3} tcg-at-platformManufacturer OBJECT IDENTIFIER ::= {tcg-attribute 4} tcg-at-platformModel OBJECT IDENTIFIER ::= {tcg-attribute 5} tcg-at-platformVersion OBJECT IDENTIFIER ::= {tcg-attribute 6} tcg-at-tpmSpecification OBJECT IDENTIFIER ::= {tcg-attribute 16} tcg-kp-EKCertificate OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) international-organizations(23) tcg(133) kp(8) 1 } TPMSpecificationInfo ::= SEQUENCE { tpmSpecificationSeq TPMSpecificationSeq } TPMSpecificationSeq ::= SEQUENCE { id OBJECT IDENTIFIER, tpmSpecificationSet TPMSpecificationSet } TPMSpecificationSet ::= SET { tpmSpecification TPMSpecification } TPMSpecification ::= SEQUENCE { family UTF8String, level INTEGER, revision INTEGER } TPMManufacturerInfo ::= SEQUENCE { tpmManufacturerSet TPMManufacturerSet, tpmModelSet TPMModelSet, tpmVersionSet TPMVersionSet } TPMManufacturerSet ::= SET { tpmManufacturer TPMManufacturer } TPMManufacturer ::= SEQUENCE { id OBJECT IDENTIFIER, manufacturer UTF8String } TPMModelSet ::= SET { tpmModel TPMModel } TPMModel ::= SEQUENCE { id OBJECT IDENTIFIER, model UTF8String } TPMVersionSet ::= SET { tpmVersion TPMVersion } TPMVersion ::= SEQUENCE { id OBJECT IDENTIFIER, version UTF8String } PlatformManufacturerInfo ::= SEQUENCE { platformManufacturerSet PlatformManufacturerSet, platformModelSet PlatformModelSet, platformVersionSet PlatformVersionSet } PlatformManufacturerSet ::= SET { platformManufacturer PlatformManufacturer } PlatformManufacturer ::= SEQUENCE { id OBJECT IDENTIFIER, manufacturer UTF8String } PlatformModelSet ::= SET { platformModel PlatformModel } PlatformModel ::= SEQUENCE { id OBJECT IDENTIFIER, model UTF8String } PlatformVersionSet ::= SET { platformVersion PlatformVersion } PlatformVersion ::= SEQUENCE { id OBJECT IDENTIFIER, version UTF8String } PlatformCertificateSAN ::= SEQUENCE OF ANY TPMEKCertExtendedKeyUsage ::= SEQUENCE { id OBJECT IDENTIFIER } END swtpm-0.6.3/src/swtpm_cert/tpm_asn1.h000066400000000000000000000070551421141172300175460ustar00rootroot00000000000000#if HAVE_CONFIG_H # include "config.h" #endif #include const asn1_static_node tpm_asn1_tab[] = { { "TPM", 536875024, NULL }, { NULL, 1073741836, NULL }, { "tcg", 1879048204, NULL }, { "joint-iso-itu-t", 1073741825, "2"}, { "international-organizations", 1073741825, "23"}, { "tcg", 1, "133"}, { "tcg-attribute", 1879048204, NULL }, { NULL, 1073741825, "tcg"}, { NULL, 1, "2"}, { "tcg-at-tpmManufacturer", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "1"}, { "tcg-at-tpmModel", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "2"}, { "tcg-at-tpmVersion", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "3"}, { "tcg-at-platformManufacturer", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "4"}, { "tcg-at-platformModel", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "5"}, { "tcg-at-platformVersion", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "6"}, { "tcg-at-tpmSpecification", 1879048204, NULL }, { NULL, 1073741825, "tcg-attribute"}, { NULL, 1, "16"}, { "tcg-kp-EKCertificate", 1879048204, NULL }, { "joint-iso-itu-t", 1073741825, "2"}, { "international-organizations", 1073741825, "23"}, { "tcg", 1073741825, "133"}, { "kp", 1073741825, "8"}, { NULL, 1, "1"}, { "TPMSpecificationInfo", 1610612741, NULL }, { "tpmSpecificationSeq", 2, "TPMSpecificationSeq"}, { "TPMSpecificationSeq", 1610612741, NULL }, { "id", 1073741836, NULL }, { "tpmSpecificationSet", 2, "TPMSpecificationSet"}, { "TPMSpecificationSet", 1610612750, NULL }, { "tpmSpecification", 201326594, "TPMSpecification"}, { "TPMSpecification", 1610612741, NULL }, { "family", 1073741858, NULL }, { "level", 1073741827, NULL }, { "revision", 3, NULL }, { "TPMManufacturerInfo", 1610612741, NULL }, { "tpmManufacturerSet", 1073741826, "TPMManufacturerSet"}, { "tpmModelSet", 1073741826, "TPMModelSet"}, { "tpmVersionSet", 2, "TPMVersionSet"}, { "TPMManufacturerSet", 1610612750, NULL }, { "tpmManufacturer", 201326594, "TPMManufacturer"}, { "TPMManufacturer", 1610612741, NULL }, { "id", 1073741836, NULL }, { "manufacturer", 34, NULL }, { "TPMModelSet", 1610612750, NULL }, { "tpmModel", 201326594, "TPMModel"}, { "TPMModel", 1610612741, NULL }, { "id", 1073741836, NULL }, { "model", 34, NULL }, { "TPMVersionSet", 1610612750, NULL }, { "tpmVersion", 201326594, "TPMVersion"}, { "TPMVersion", 1610612741, NULL }, { "id", 1073741836, NULL }, { "version", 34, NULL }, { "PlatformManufacturerInfo", 1610612741, NULL }, { "platformManufacturerSet", 1073741826, "PlatformManufacturerSet"}, { "platformModelSet", 1073741826, "PlatformModelSet"}, { "platformVersionSet", 2, "PlatformVersionSet"}, { "PlatformManufacturerSet", 1610612750, NULL }, { "platformManufacturer", 201326594, "PlatformManufacturer"}, { "PlatformManufacturer", 1610612741, NULL }, { "id", 1073741836, NULL }, { "manufacturer", 34, NULL }, { "PlatformModelSet", 1610612750, NULL }, { "platformModel", 201326594, "PlatformModel"}, { "PlatformModel", 1610612741, NULL }, { "id", 1073741836, NULL }, { "model", 34, NULL }, { "PlatformVersionSet", 1610612750, NULL }, { "platformVersion", 201326594, "PlatformVersion"}, { "PlatformVersion", 1610612741, NULL }, { "id", 1073741836, NULL }, { "version", 34, NULL }, { "PlatformCertificateSAN", 1610612747, NULL }, { NULL, 13, NULL }, { "TPMEKCertExtendedKeyUsage", 536870917, NULL }, { "id", 12, NULL }, { NULL, 0, NULL } }; swtpm-0.6.3/src/swtpm_ioctl/000077500000000000000000000000001421141172300160215ustar00rootroot00000000000000swtpm-0.6.3/src/swtpm_ioctl/Makefile.am000066400000000000000000000007521421141172300200610ustar00rootroot00000000000000# # src/cuse_tpm_ioctl/Makefile.am # # For the license, see the LICENSE file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = bin_PROGRAMS = \ swtpm_ioctl swtpm_ioctl_SOURCES = tpm_ioctl.c swtpm_ioctl_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ $(MY_CFLAGS) \ $(CFLAGS) \ $(HARDENING_CFLAGS) swtpm_ioctl_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) EXTRA_DIST = \ README CLEANFILES = *.gcno *.gcda *.gcov swtpm-0.6.3/src/swtpm_ioctl/README000066400000000000000000000002331421141172300166770ustar00rootroot00000000000000swtpm_ioctl is a tool that sends out-of-band control commands to the CUSE TPM (swtpm_cuse). For further information, check the manpage 'man swtpm_ioctl'. swtpm-0.6.3/src/swtpm_ioctl/tpm_ioctl.c000066400000000000000000001225711421141172300201670ustar00rootroot00000000000000/* * tpm_ioctl -- ioctl utility for the TPM * * Authors: David Safford * Stefan Berger * * (c) Copyright IBM Corporation 2014 - 2016. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of the IBM Corporation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * tool for using 'swtpm cuse' ioctls * * cuse_tpm_ioctl [ -c | -i | -s | -e | -l num | -C | -v ] devicepath * -c get ptm capabilities * -i do a hardware TPM_Init * -s shutdown tpm_server_cuse * -e get tpmEstablished bit * -l set locality to num * -h hash the given data * -v store volatile data to file * -C cancel an ongoing TPM command */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sys_dependencies.h" #include "swtpm.h" #define DEFAULT_TCP_PORT 6546 #define devtoh32(is_chardev, x) (is_chardev ? x : be32toh(x)) #define htodev32(is_chardev, x) (is_chardev ? x : htobe32(x)) #define devtoh64(is_chardev, x) (is_chardev ? x : be64toh(x)) #define htodev64(is_chardev, x) (is_chardev ? x : htobe64(x)) /* for OpenBSD */ #ifndef _IOC_NRSHIFT # define _IOC_NRSHIFT 0 #endif #ifndef _IOC_NRMASK # define _IOC_NRMASK 255 #endif /* poll timeout that takes into account a busy swtpm creating a key */ #define DEFAULT_POLL_TIMEOUT 10000 /* ms */ static unsigned long ioctl_to_cmd(unsigned long ioctlnum) { /* the ioctl number contains the command number - 1 */ return ((ioctlnum >> _IOC_NRSHIFT) & _IOC_NRMASK) + 1; } /* * ctrlcmd - send a control command * * This function returns -1 on on error with errno indicating the error. * In case an ioctl is used, it returns 0 on success; otherwise * it returns the number of bytes received in the response. */ static int ctrlcmd(int fd, unsigned long cmd, void *msg, size_t msg_len_in, size_t msg_len_out) { struct stat statbuf; int n; n = fstat(fd, &statbuf); if (n < 0) { fprintf(stderr, "fstat failed: %s\n", strerror(errno)); return -1; } if ((statbuf.st_mode & S_IFMT) == S_IFCHR) { n = ioctl(fd, cmd, msg); } else { uint32_t cmd_no = htobe32(ioctl_to_cmd(cmd)); struct iovec iov[2] = { { .iov_base = &cmd_no, .iov_len = sizeof(cmd_no), }, { .iov_base = msg, .iov_len = msg_len_in, }, }; n = writev(fd, iov, 2); if (n > 0) { if (msg_len_out > 0) { struct pollfd fds = { .fd = fd, .events = POLLIN, }; n = poll(&fds, 1, DEFAULT_POLL_TIMEOUT); if (n == 1) { n = read(fd, msg, msg_len_out); } else if (n == 0) { n = -1; errno = ETIMEDOUT; } } else { /* we read 0 bytes */ n = 0; } } } return n; } /* * Do PTM_HASH_START, PTM_HASH_DATA, PTM_HASH_END on the * data. */ static int do_hash_start_data_end(int fd, bool is_chardev, const char *input) { ptm_res res; int n; size_t idx; ptm_hdata hdata; size_t inputlen; memset(&hdata, 0, sizeof(hdata)); if (!input) { fprintf(stderr, "Input buffer for hashing must not be NULL.\n"); return 1; } /* hash string given on command line */ n = ctrlcmd(fd, PTM_HASH_START, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_HASH_START: " "%s\n", strerror(errno)); return 1; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_HASH_START: 0x%x\n", devtoh32(is_chardev, res)); return 1; } inputlen = strlen(input); if (inputlen == 1 && input[0] == '-') { /* read data from stdin */ while (1) { idx = 0; int c = 0; while (idx < sizeof(hdata.u.req.data)) { c = fgetc(stdin); if (c == EOF) break; hdata.u.req.data[idx] = (char)c; idx++; } hdata.u.req.length = htodev32(is_chardev, idx); n = ctrlcmd(fd, PTM_HASH_DATA, &hdata, offsetof(ptm_hdata, u.req.data) + idx, sizeof(hdata.u.resp)); res = devtoh32(is_chardev, hdata.u.resp.tpm_result); if (n < 0 || res != 0 || c == EOF) break; } } else { idx = 0; while (idx < inputlen) { size_t tocopy = inputlen - idx; if (tocopy > sizeof(hdata.u.req.data)) tocopy = sizeof(hdata.u.req.data); hdata.u.req.length = htodev32(is_chardev, tocopy); memcpy(hdata.u.req.data, &input[idx], tocopy); idx += tocopy; n = ctrlcmd(fd, PTM_HASH_DATA, &hdata, offsetof(ptm_hdata, u.req.data) + tocopy, sizeof(hdata.u.resp)); res = devtoh32(is_chardev, hdata.u.resp.tpm_result); if (n < 0 || res != 0) break; } } if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_HASH_DATA: " "%s\n", strerror(errno)); return 1; } if (res != 0) { fprintf(stderr, "TPM result from PTM_HASH_DATA: 0x%x\n", res); return 1; } n = ctrlcmd(fd, PTM_HASH_END, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_HASH_END: " "%s\n", strerror(errno)); return 1; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_HASH_END: 0x%x\n", devtoh32(is_chardev, res)); return 1; } return 0; } static uint32_t get_blobtype(const char *blobname) { if (!blobname) return 0; if (!strcmp(blobname, "permanent")) return PTM_BLOB_TYPE_PERMANENT; if (!strcmp(blobname, "volatile")) return PTM_BLOB_TYPE_VOLATILE; if (!strcmp(blobname, "savestate")) return PTM_BLOB_TYPE_SAVESTATE; return 0; } /* * do_save_state_blob: Get a state blob from the TPM and store it into the * given file * @fd: file descriptor to talk to the TPM * @is_chardev: whether @fd is a character device using ioctl * @blobtype: the name of the blobtype * @filename: name of the file to store the blob into * */ static int do_save_state_blob(int fd, bool is_chardev, const char *blobtype, const char *filename, size_t buffersize) { int file_fd; ptm_res res; ptm_getstate pgs; uint16_t offset; ssize_t numbytes, remain = -1; bool had_error; int n; uint32_t bt; unsigned char *buffer = NULL; uint32_t recvd_bytes; memset(&pgs, 0, sizeof(pgs)); bt = get_blobtype(blobtype); if (!bt) { fprintf(stderr, "Unknown TPM state type '%s'", blobtype); return 1; } file_fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); if (file_fd < 0) { fprintf(stderr, "Could not open file '%s' for writing: %s\n", filename, strerror(errno)); return 1; } if (!is_chardev) buffersize = 4096; had_error = false; offset = 0; while (true) { /* fill out request every time since response may change it */ pgs.u.req.state_flags = htodev32(is_chardev, PTM_STATE_FLAG_DECRYPTED); pgs.u.req.type = htodev32(is_chardev, bt); pgs.u.req.offset = htodev32(is_chardev, offset); n = ctrlcmd(fd, PTM_GET_STATEBLOB, &pgs, sizeof(pgs.u.req), sizeof(pgs.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_GET_STATEBLOB: " "%s\n", strerror(errno)); had_error = true; break; } res = devtoh32(is_chardev, pgs.u.resp.tpm_result); if (res != 0 && (res & TPM_NON_FATAL) == 0) { fprintf(stderr, "TPM result from PTM_GET_STATEBLOB: 0x%x\n", res); had_error = true; break; } if (remain == -1) remain = devtoh32(is_chardev, pgs.u.resp.totlength); if (!is_chardev) { /* we receive a part of the chunk */ recvd_bytes = n - offsetof(ptm_getstate, u.resp.data); if ((int32_t)recvd_bytes < 0) { fprintf(stderr, "Too few bytes in response"); had_error = true; break; } } else { recvd_bytes = MIN(devtoh32(is_chardev, pgs.u.resp.length), sizeof(pgs.u.resp.data)); } numbytes = write(file_fd, pgs.u.resp.data, recvd_bytes); if (numbytes < 0 || (uint32_t)numbytes != recvd_bytes) { fprintf(stderr, "Could not write to file '%s': %s\n", filename, strerror(errno)); had_error = true; break; } remain -= recvd_bytes; /* done when the last byte was received */ if (offset + recvd_bytes >= devtoh32(is_chardev, pgs.u.resp.totlength)) break; if (buffersize) { /* continue with the read interface */ buffer = malloc(buffersize); if (!buffer) { fprintf(stderr, "Could not allocate buffer with %zu bytes.", buffersize); had_error = true; break; } while (true) { /* read from TPM */ n = read(fd, buffer, buffersize); if (n < 0) { fprintf(stderr, "Could not read from TPM: %s\n", strerror(errno)); had_error = true; break; } remain -= n; numbytes = write(file_fd, buffer, n); if (numbytes < 0) { fprintf(stderr, "Could not write to file '%s': %s\n", filename, strerror(errno)); had_error = true; break; } if (remain <= 0) break; } break; } else { offset += devtoh32(is_chardev, pgs.u.resp.length); } if (!is_chardev) break; } close(file_fd); free(buffer); if (had_error) return 1; if (remain != 0) { fprintf(stderr, "Unexpected number of remaining bytes: %zd\n", remain); return 1; } return 0; } /* * do_load_state_blob: Load a TPM state blob from a file and load it into the * TPM * @fd: file descriptor to talk to the TPM * @is_chardev: whether @fd is a character device * @blobtype: the name of the blobtype * @filename: name of the file to store the blob into * @buffersize: the size of the buffer to use via write() interface */ static int do_load_state_blob(int fd, bool is_chardev, const char *blobtype, const char *filename, size_t buffersize) { int file_fd; ptm_res res; ptm_setstate pss; ssize_t numbytes; bool had_error; int n; uint32_t bt; unsigned char *buffer = NULL; struct stat statbuf; bt = get_blobtype(blobtype); if (!bt) { fprintf(stderr, "Unknown TPM state type '%s'", blobtype); return 1; } if (!filename) { fprintf(stderr, "Filename parameter must not be NULL\n"); return 1; } file_fd = open(filename, O_RDONLY); if (file_fd < 0) { fprintf(stderr, "Could not open file '%s' for reading: %s\n", filename, strerror(errno)); return 1; } if (!is_chardev) { n = fstat(file_fd, &statbuf); if (n < 0) { fprintf(stderr, "Could not stat file '%s': %s\n", filename, strerror(errno)); close(file_fd); return 1; } buffersize = statbuf.st_size; } had_error = false; if (!buffersize) { /* use only the ioctl interface for the transfer */ while (true) { size_t returnsize; /* fill out request every time since response may change it */ pss.u.req.state_flags = htodev32(is_chardev, 0); pss.u.req.type = htodev32(is_chardev, bt); numbytes = read(file_fd, pss.u.req.data, sizeof(pss.u.req.data)); if (numbytes < 0) { fprintf(stderr, "Could not read from file '%s': %s\n", filename, strerror(errno)); had_error = true; break; } pss.u.req.length = htodev32(is_chardev, (uint32_t)numbytes); /* the returnsize is zero on all intermediate packets */ returnsize = ((size_t)numbytes < sizeof(pss.u.req.data)) ? sizeof(pss) : 0; n = ctrlcmd(fd, PTM_SET_STATEBLOB, &pss, offsetof(ptm_setstate, u.req.data) + numbytes, returnsize); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_SET_STATEBLOB: " "%s\n", strerror(errno)); had_error = true; break; } res = devtoh32(is_chardev, pss.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_STATEBLOB: 0x%x\n", res); had_error = true; break; } if ((size_t)numbytes < sizeof(pss.u.req.data)) break; } } else { buffer = malloc(buffersize); if (!buffer) { fprintf(stderr, "Could not allocate buffer with %zu bytes.", buffersize); had_error = true; goto cleanup; } memset(&pss, 0, sizeof(pss)); pss.u.req.state_flags = htodev32(is_chardev, 0); pss.u.req.type = htodev32(is_chardev, bt); /* will use write interface */ if (is_chardev) { pss.u.req.length = htodev32(is_chardev, 0); } else { pss.u.req.length = htodev32(is_chardev, buffersize); } n = ctrlcmd(fd, PTM_SET_STATEBLOB, &pss, offsetof(ptm_setstate, u.req.data) + 0, 0); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_SET_STATEBLOB: " "%s\n", strerror(errno)); had_error = 1; goto cleanup; } res = devtoh32(is_chardev, pss.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_STATEBLOB: 0x%x\n", res); had_error = 1; goto cleanup; } while (true) { n = read(file_fd, buffer, buffersize); if (n < 0) { fprintf(stderr, "Could not read from file: %s\n", strerror(errno)); had_error = 1; goto cleanup; } if (n != write(fd, buffer, n)) { fprintf(stderr, "Could not write to file: %s\n", strerror(errno)); had_error = 1; goto cleanup; } if (!is_chardev) { n = read(fd, &pss.u.resp, sizeof(pss.u.resp)); if (n < 0) { fprintf(stderr, "Error reading response: %s\n", strerror(errno)); had_error = 1; goto cleanup; } if (n != sizeof(pss.u.resp)) { fprintf(stderr, "Did not get enough response bytes " "from PTM_SET_STATE_BLOB: %d\n", n); had_error = 1; goto cleanup; } res = devtoh32(is_chardev, pss.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_STATEBLOB: 0x%x\n", res); had_error = 1; goto cleanup; } break; } if ((size_t)n < buffersize) { /* close transfer with the ioctl() */ pss.u.req.state_flags = htodev32(is_chardev, 0); pss.u.req.type = htodev32(is_chardev, bt); /* end the transfer */ pss.u.req.length = htodev32(is_chardev, 0); n = ctrlcmd(fd, PTM_SET_STATEBLOB, &pss, offsetof(ptm_setstate, u.req.data) + 0, sizeof(pss.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute ioctl PTM_SET_STATEBLOB: " "%s\n", strerror(errno)); had_error = 1; goto cleanup; } res = devtoh32(is_chardev, pss.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_STATEBLOB: 0x%x\n", res); had_error = 1; goto cleanup; } break; } } } cleanup: close(file_fd); free(buffer); if (had_error) return 1; return 0; } static int change_fd_flags(int fd, int flags_to_clear, int flags_to_set) { int n; int orig_flags = fcntl(fd, F_GETFL, 0); if (orig_flags == -1) { fprintf(stderr, "fcntl(F_GETFL) failed: %s\n", strerror(errno)); return -1; } else { int flags = (orig_flags & ~flags_to_clear) | flags_to_set; n = fcntl(fd, F_SETFL, flags); if (n == -1) { fprintf(stderr, "fcntl(F_SETFL) failed: %s\n", strerror(errno)); return -1; } } return orig_flags; } /* Create a connection by setting the given file descriptor to non-blocking. * If the function returns successfully, the file descriptor will be blocking * again. */ static int connect_nonblock(int fd, const struct sockaddr *addr, socklen_t addrlen, int allowed_errno, const char *socktype) { int n, sockerr; socklen_t optlen = sizeof(sockerr); #if !defined(__CYGWIN__) int orig_flags = change_fd_flags(fd, 0, O_NONBLOCK); #else int orig_flags = change_fd_flags(fd, 0, 0); #endif n = connect(fd, addr, addrlen); /* n < 0: it must fail with EAGAIN (Unix socket) and then we have to poll * and get SO_ERROR * n = 0: connection is established */ if (n < 0 && errno != allowed_errno) { fprintf(stderr, "Connect failed: %s\n", strerror(errno)); return -1; } else if (n < 0) { struct pollfd pollfd = { .fd = fd, .events = POLLOUT, }; n = poll(&pollfd, 1, DEFAULT_POLL_TIMEOUT); /* Unix socket may return POLLHUP on error */ if (n != 1 || (pollfd.revents & ~POLLOUT) != 0) { fprintf(stderr, "Could not connect using %s socket.\n", socktype); return -1; } n = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &optlen); if (n < 0) { fprintf(stderr, "getsockopt(SO_ERROR) failed: %s\n", strerror(errno)); return -1; } if (sockerr != 0) { fprintf(stderr, "Could not connect using %s socket.\n", socktype); return -1; } } return change_fd_flags(fd, ~0, orig_flags); } static int open_connection(const char *devname, char *tcp_hostname, unsigned short tcp_port, const char *unix_path) { int fd = -1; if (devname) { fd = open(devname, O_RDWR); if (fd < 0) { fprintf(stderr, "Unable to open device '%s'.\n", devname); } } else if (tcp_hostname) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, }; struct addrinfo *ais = NULL, *ai; char portstr[10]; snprintf(portstr, sizeof(portstr), "%u", tcp_port); int err = getaddrinfo(tcp_hostname, portstr, &hints, &ais); if (err != 0) { fprintf(stderr, "getaddrinfo failed on host '%s': %s\n", tcp_hostname, gai_strerror(err)); return -1; } for (ai = ais; ai != NULL; ai = ai->ai_next) { fd = socket(ai->ai_family, ai->ai_socktype, 0); if (fd < 0) continue; if (connect(fd, (struct sockaddr *)ai->ai_addr, ai->ai_addrlen) == 0) break; close(fd); fd = -1; } freeaddrinfo(ais); if (fd < 0) { fprintf(stderr, "Could not connect to host '%s' on port '%u' " "using TCP socket: %s\n", tcp_hostname, tcp_port, strerror(errno)); } } else if (unix_path) { struct sockaddr_un addr; size_t unix_path_len = strlen(unix_path) + 1; if (unix_path_len > sizeof(addr.sun_path)) { fprintf(stderr, "Socket path is too long.\n"); return -1; } fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd > 0) { addr.sun_family = AF_UNIX; strncpy(addr.sun_path, unix_path, unix_path_len); if (connect_nonblock(fd, (struct sockaddr*)&addr, sizeof(addr), EAGAIN, "UnixIO") < 0) { close(fd); fd = -1; } } } return fd; } static int parse_tcp_optarg(char *optarg, char **tcp_hostname, int *tcp_port) { char *pos = strrchr(optarg, ':'); int n; *tcp_port = DEFAULT_TCP_PORT; if (!pos) { /* */ *tcp_hostname = strdup(optarg); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } return 0; } else if (pos == optarg) { if (strlen(&pos[1]) != 0) { /* : (not just ':') */ n = sscanf(&pos[1], "%u", tcp_port); if (n != 1) { fprintf(stderr, "Invalid port '%s'\n", &pos[1]); return -1; } if (*tcp_port >= 65536) { fprintf(stderr, "Port '%s' outside valid range.\n", &optarg[1]); return -1; } } *tcp_hostname = strdup("127.0.0.1"); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } } else { /* : */ n = sscanf(&pos[1], "%u", tcp_port); if (n != 1) { fprintf(stderr, "Invalid port '%s'\n", &pos[1]); return -1; } if (*tcp_port >= 65536) { fprintf(stderr, "Port '%s' outside valid range.\n", &optarg[1]); return -1; } *tcp_hostname = strndup(optarg, pos - optarg); if (*tcp_hostname == NULL) { fprintf(stderr, "Out of memory.\n"); return -1; } } return 0; } static void versioninfo(const char *prgname) { fprintf(stdout, "TPM emulator control tool version %d.%d.%d, Copyright (c) 2015 IBM Corp.\n" ,SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); } static void usage(const char *prgname) { versioninfo(prgname); fprintf(stdout, "\n" "Usage: %s command \n" "\n" "The following commands are supported:\n" "--tpm-device : use the given device; default is /dev/tpm0\n" "--tcp []:[]: connect to TPM on given host and port;\n" " default host is 127.0.0.1, default port is %u\n" "--unix : connect to TPM using UnixIO socket\n" "-c : get ptm capabilities\n" "-i : do a hardware TPM_Init; if volatile state is found,\n" " it will resume the TPM with it and delete it\n" " afterwards\n" "--stop : stop the TPM without exiting\n" "-s : shutdown the TPM; stops and exists\n" "-e : get the tpmEstablished bit\n" "-r : reset the tpmEstablished bit; use the given locality\n" "-v : store the TPM's volatile data\n" "-C : cancel an ongoing TPM command\n" "-l : set the locality to the given number; valid\n" " localities are 0-4\n" "-h : hash the given data; if data is '-' then data are\n" " read from stdin\n" "--save : store the TPM state blob of given type in a file;\n" " type may be one of volatile, permanent, or savestate\n" "--load : load the TPM state blob of given type from a file;\n" " type may be one of volatile, permanent, or savestate\n" "-g : get configuration flags indicating which keys are in\n" " use\n" "-b : set the buffer size of the TPM and get its current\n" " size; get minimum and maximum supported sizes\n" "--info : get TPM implementation specific information;\n" " flags must be an integer value\n" "--version : display version and exit\n" "--help : display help screen and exit\n" "\n" , prgname, DEFAULT_TCP_PORT); } int main(int argc, char *argv[]) { int fd, n; ptm_est est; ptm_reset_est reset_est; ptm_loc loc; ptm_cap cap; ptm_res res; ptm_init init; ptm_getconfig cfg; ptm_setbuffersize psbs; ptm_getinfo pgi; char *tmp; size_t buffersize = 0; static struct option long_options[] = { {"tpm-device", required_argument, NULL, 'D'}, {"tcp", required_argument, NULL, 'T'}, {"unix", required_argument, NULL, 'U'}, {"c", no_argument, NULL, 'c'}, {"i", no_argument, NULL, 'i'}, {"stop", no_argument, NULL, 't'}, {"s", no_argument, NULL, 's'}, {"e", no_argument, NULL, 'e'}, {"r", required_argument, NULL, 'r'}, {"v", no_argument, NULL, 'v'}, {"C", no_argument, NULL, 'C'}, {"l", required_argument, NULL, 'l'}, {"h", required_argument, NULL, 'h'}, {"g", no_argument, NULL, 'g'}, {"b", required_argument, NULL, 'b'}, {"save", required_argument, NULL, 'S'}, {"load", required_argument, NULL, 'L'}, {"version", no_argument, NULL, 'V'}, {"info", required_argument, NULL, 'I'}, {"help", no_argument, NULL, 'H'}, {NULL, 0, NULL, 0}, }; int opt, option_index = 0; const char *command = NULL, *pcommand = NULL; const char *blobtype = NULL, *blobfile = NULL, *hashdata = NULL; const char *tpm_device = NULL, *unix_path = NULL; char *tcp_hostname = NULL; unsigned int locality = 0; unsigned int tpmbuffersize = 0; int tcp_port = -1; bool is_chardev; unsigned long int info_flags = 0; char *endptr = NULL; int ret = EXIT_FAILURE; #if defined __NetBSD__ while ((opt = getopt_long(argc, argv, "D:T:U:citser:vCl:h:gb:S:L:VI:H", long_options, &option_index)) != -1) { #else while ((opt = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) { #endif switch (opt) { case 'D': tpm_device = optarg; break; case 'T': if (parse_tcp_optarg(optarg, &tcp_hostname, &tcp_port) < 0) return EXIT_FAILURE; break; case 'U': unix_path = optarg; break; case 'c': case 'i': case 't': case 's': case 'e': case 'v': case 'C': case 'g': command = argv[optind - 1]; break; case 'h': command = argv[optind - 2]; hashdata = argv[optind - 1]; break; case 'r': case 'l': command = argv[optind - 2]; if (sscanf(argv[optind - 1], "%u", &locality) != 1) { fprintf(stderr, "Could not get locality number from %s.\n", argv[optind - 1]); goto exit; } if (locality > 4) { fprintf(stderr, "Locality outside valid range of [0..4].\n"); goto exit; } break; case 'S': if (optind == argc || !strncmp(argv[optind], "-", 1) || !strncmp(argv[optind], "--", 2)) { fprintf(stderr, "Missing filename argument for --save option\n"); goto exit; } command = argv[optind - 2]; blobtype = argv[optind - 1]; blobfile = argv[optind]; optind++; break; case 'L': if (optind == argc || !strncmp(argv[optind], "-", 1) || !strncmp(argv[optind], "--", 2)) { fprintf(stderr, "Missing filename argument for --load option\n"); goto exit; } command = argv[optind - 2]; blobtype = argv[optind - 1]; blobfile = argv[optind]; optind++; break; case 'b': command = argv[optind - 2]; if (sscanf(argv[optind - 1], "%u", &tpmbuffersize) != 1) { fprintf(stderr, "Could not get buffersize from %s.\n", argv[optind - 1]); goto exit; } break; case 'I': command = argv[optind - 2]; errno = 0; info_flags = strtoul(argv[optind - 1], &endptr, 0); if (errno || endptr[0] != '\0') { fprintf(stderr, "Cannot parse info flags.\n"); goto exit; } break; case 'V': versioninfo(argv[0]); ret = EXIT_SUCCESS; goto exit; case 'H': usage(argv[0]); ret = EXIT_SUCCESS; goto exit; } if (!pcommand) { pcommand = command; } else { if (command != pcommand) { fprintf(stderr, "Only one command may be given.\n"); goto exit; } } } if (!command) { fprintf(stderr, "No valid command.\n"); goto exit; } if (!tpm_device && !tcp_hostname && !unix_path) { if (optind == argc) { fprintf(stderr, "Error: Missing device name.\n"); goto exit; } tpm_device = argv[optind]; } is_chardev = (tpm_device != NULL); if (is_chardev) { tmp = getenv("SWTPM_IOCTL_BUFFERSIZE"); if (tmp) { if (sscanf(tmp, "%zu", &buffersize) != 1 || buffersize < 1) buffersize = 1; } } else { if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { fprintf(stderr, "Could not install signal handler for SIGPIPE."); goto exit; } } fd = open_connection(tpm_device, tcp_hostname, tcp_port, unix_path); if (fd < 0) { goto exit; } if (!strcmp(command, "-c")) { n = ctrlcmd(fd, PTM_GET_CAPABILITY, &cap, 0, sizeof(cap)); if (n < 0) { fprintf(stderr, "Could not execute PTM_GET_CAPABILITY: " "%s\n", strerror(errno)); goto exit; } /* no tpm_result here */ printf("ptm capability is 0x%" PRIx64 "\n", (uint64_t)devtoh64(is_chardev, cap)); } else if (!strcmp(command, "-i")) { init.u.req.init_flags = htodev32(is_chardev, PTM_INIT_FLAG_DELETE_VOLATILE); n = ctrlcmd(fd, PTM_INIT, &init, sizeof(init.u.req), sizeof(init.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_INIT: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, init.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_INIT: 0x%x\n", res); goto exit; } } else if (!strcmp(command, "-e")) { n = ctrlcmd(fd, PTM_GET_TPMESTABLISHED, &est, 0, sizeof(est.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_GET_ESTABLISHED: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, est.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_GET_TPMESTABLISHED: 0x%x\n", res); goto exit; } printf("tpmEstablished is %d\n", est.u.resp.bit); } else if (!strcmp(command, "-r")) { memset(&reset_est, 0, sizeof(reset_est)); reset_est.u.req.loc = locality; n = ctrlcmd(fd, PTM_RESET_TPMESTABLISHED, &reset_est, sizeof(reset_est.u.req), sizeof(reset_est.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_RESET_ESTABLISHED: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, reset_est.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_RESET_TPMESTABLISHED: 0x%x\n", res); goto exit; } } else if (!strcmp(command, "-s")) { n = ctrlcmd(fd, PTM_SHUTDOWN, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute PTM_SHUTDOWN: " "%s\n", strerror(errno)); goto exit; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_SHUTDOWN: 0x%x\n", devtoh32(is_chardev, res)); goto exit; } } else if (!strcmp(command, "--stop")) { n = ctrlcmd(fd, PTM_STOP, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute PTM_STOP: " "%s\n", strerror(errno)); goto exit; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_STOP: 0x%x\n", devtoh32(is_chardev, res)); goto exit; } } else if (!strcmp(command, "-l")) { loc.u.req.loc = locality; n = ctrlcmd(fd, PTM_SET_LOCALITY, &loc, sizeof(loc.u.req), sizeof(loc.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_SET_LOCALITY: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, loc.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_LOCALITY: 0x%x\n", res); goto exit; } } else if (!strcmp(command, "-h")) { if (do_hash_start_data_end(fd, is_chardev, hashdata)) { goto exit; } } else if (!strcmp(command, "-C")) { n = ctrlcmd(fd, PTM_CANCEL_TPM_CMD, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute PTM_CANCEL_TPM_CMD: " "%s\n", strerror(errno)); goto exit; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_CANCEL_TPM_CMD: 0x%x\n", devtoh32(is_chardev, res)); goto exit; } } else if (!strcmp(command, "-v")) { n = ctrlcmd(fd, PTM_STORE_VOLATILE, &res, 0, sizeof(res)); if (n < 0) { fprintf(stderr, "Could not execute PTM_STORE_VOLATILE: " "%s\n", strerror(errno)); goto exit; } if (devtoh32(is_chardev, res) != 0) { fprintf(stderr, "TPM result from PTM_STORE_VOLATILE: 0x%x\n", devtoh32(is_chardev, res)); goto exit; } } else if (!strcmp(command, "--save")) { if (do_save_state_blob(fd, is_chardev, blobtype, blobfile, buffersize)) goto exit; } else if (!strcmp(command, "--load")) { if (do_load_state_blob(fd, is_chardev, blobtype, blobfile, buffersize)) goto exit; } else if (!strcmp(command, "-g")) { n = ctrlcmd(fd, PTM_GET_CONFIG, &cfg, 0, sizeof(cfg)); if (n < 0) { fprintf(stderr, "Could not execute PTM_GET_CONFIG: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, cfg.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_GET_CONFIG: 0x%x\n", res); goto exit; } printf("ptm configuration flags: 0x%x\n", devtoh32(is_chardev, cfg.u.resp.flags)); } else if (!strcmp(command, "-b")) { memset(&psbs, 0, sizeof(psbs)); psbs.u.req.buffersize = htodev32(is_chardev, tpmbuffersize); n = ctrlcmd(fd, PTM_SET_BUFFERSIZE, &psbs, sizeof(psbs.u.req), sizeof(psbs.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_SET_BUFFERSIZE: " "%s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, psbs.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_SET_BUFFERSIZE: 0x%x\n", res); goto exit; } printf("TPM buffersize: %u\n" "minimum size : %u\n" "maximum size : %u\n", devtoh32(is_chardev, psbs.u.resp.buffersize), devtoh32(is_chardev, psbs.u.resp.minsize), devtoh32(is_chardev, psbs.u.resp.maxsize)); } else if (!strcmp(command, "--info")) { memset(&pgi, 0, sizeof(pgi)); pgi.u.req.flags = htodev64(is_chardev, info_flags); pgi.u.req.offset = htodev64(is_chardev, 0); n = ctrlcmd(fd, PTM_GET_INFO, &pgi, sizeof(pgi.u.req), sizeof(pgi.u.resp)); if (n < 0) { fprintf(stderr, "Could not execute PTM_GET_INFO: %s\n", strerror(errno)); goto exit; } res = devtoh32(is_chardev, pgi.u.resp.tpm_result); if (res != 0) { fprintf(stderr, "TPM result from PTM_GET_INFO: 0x%x\n", res); goto exit; } printf("%s\n", pgi.u.resp.buffer); } else { usage(argv[0]); goto exit; } ret = EXIT_SUCCESS; exit: free(tcp_hostname); return ret; } swtpm-0.6.3/src/swtpm_setup/000077500000000000000000000000001421141172300160475ustar00rootroot00000000000000swtpm-0.6.3/src/swtpm_setup/Makefile.am000066400000000000000000000017761421141172300201160ustar00rootroot00000000000000# # src/swtpm_setup/Makefile.am # # For the license, see the LICENSE file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = \ swtpm.h \ swtpm_setup.h \ swtpm_setup_utils.h bin_PROGRAMS = \ swtpm_setup swtpm_setup_SOURCES = \ swtpm.c \ swtpm_setup.c \ swtpm_setup_utils.c $(top_builddir)/src/utils/libswtpm_utils.la: $(MAKE) -C$(dir $@) swtpm_setup_DEPENDENCIES = \ $(top_builddir)/src/utils/libswtpm_utils.la swtpm_setup_LDADD = \ $(top_builddir)/src/utils/libswtpm_utils.la swtpm_setup_LDFLAGS = \ -L$(top_builddir)/src/utils -lswtpm_utils \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) \ $(GLIB_LIBS) \ $(JSON_GLIB_LIBS) \ $(LIBCRYPTO_LIBS) swtpm_setup_CFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include \ -I$(top_srcdir)/include/swtpm \ -I$(top_srcdir)/src/utils \ $(MY_CFLAGS) \ $(CFLAGS) \ $(HARDENING_CFLAGS) \ $(GLIB_CFLAGS) \ $(JSON_GLIB_CFLAGS) \ $(LIBCRYPTO_EXTRA_CFLAGS) EXTRA_DIST = \ README CLEANFILES = *.gcno *.gcda *.gcov swtpm-0.6.3/src/swtpm_setup/README000066400000000000000000000005451421141172300167330ustar00rootroot00000000000000swtpm_setup is a tool that simulates the manufacturing of a TPM and allows a user to prepare the initial state of a TPM by having the TPM create an EK, creating the EK and platform certificates for it, and saving the certificates into the NVRAM of the TPM before it is used for the first time. For further information, check the manpage 'man swtpm_setup'. swtpm-0.6.3/src/swtpm_setup/swtpm.c000066400000000000000000002040221421141172300173650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm.c: Programming of a swtpm using communication via fd-passing * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swtpm.h" #include "swtpm_utils.h" #include "tpm_ioctl.h" #include "sys_dependencies.h" #define AS2BE(VAL) (((VAL) >> 8) & 0xff), ((VAL) & 0xff) #define AS4BE(VAL) AS2BE((VAL) >> 16), AS2BE(VAL) #define AS8BE(VAL) AS4BE((VAL) >> 32), AS4BE(VAL) struct tpm_req_header { uint16_t tag; uint32_t size; uint32_t ordinal; } __attribute__((packed)); struct tpm_resp_header { uint16_t tag; uint32_t size; uint32_t errcode; } __attribute__((packed)); static int swtpm_start(struct swtpm *self) { g_autofree gchar *tpmstate_dir = g_strdup_printf("dir=%s", self->state_path); g_autofree gchar *pidfile_file = NULL; g_autofree gchar *server_fd = NULL; g_autofree gchar *ctrl_fd = NULL; g_autofree gchar *keyopts = NULL; g_autofree gchar **argv = NULL; struct stat statbuf; gboolean success; GError *error = NULL; unsigned ctr; self->pidfile = g_strjoin(G_DIR_SEPARATOR_S, self->state_path, ".swtpm_setup.pidfile", NULL); pidfile_file = g_strdup_printf("file=%s", self->pidfile); argv = concat_arrays(self->swtpm_exec_l, (gchar*[]){ "--flags", "not-need-init,startup-clear", "--tpmstate", tpmstate_dir, "--pid", pidfile_file, #if 0 "--log", "file=/tmp/log,level=20", #endif NULL }, FALSE); if (self->is_tpm2) argv = concat_arrays(argv, (gchar*[]){"--tpm2", NULL}, TRUE); if (self->keyopts != NULL) { keyopts = g_strdup(self->keyopts); argv = concat_arrays(argv, (gchar*[]){"--key", keyopts, NULL}, TRUE); } if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->ctrl_fds) != 0) { logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno)); return 1; } ctrl_fd = g_strdup_printf("type=unixio,clientfd=%d", self->ctrl_fds[1]); if (socketpair(AF_UNIX, SOCK_STREAM, 0, self->data_fds) != 0) { logerr(self->logfile, "Could not create socketpair: %s\n", strerror(errno)); return 1; } server_fd = g_strdup_printf("type=tcp,fd=%d", self->data_fds[1]); argv = concat_arrays(argv, (gchar*[]){ "--server", server_fd, "--ctrl", ctrl_fd, NULL }, TRUE); if (self->cops->remove_pidfile(self) != 0) { logerr(self->logfile, "Could not remove PID file\n"); return 1; } #if 0 { g_autofree gchar *join = g_strjoinv(" ", argv); logit(self->logfile, "Starting swtpm: %s\n", join); } #endif success = g_spawn_async(NULL, argv, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &self->pid, &error); if (!success) { logerr(self->logfile, "Could not start swtpm: %s\n", error->message); g_error_free(error); return 1; } /* wait until the pidfile appears or swtpm terminates */ for (ctr = 0; ctr < 1000; ctr++) { if (kill(self->pid, 0) < 0) { /* swtpm terminated */ self->pid = 0; logerr(self->logfile, "swtpm process terminated unexpectedly.\n"); self->cops->stop(self); return 1; } if (stat(self->pidfile, &statbuf) == 0) { printf("TPM is listening on Unix socket.\n"); return 0; } usleep(5000); } return 1; } /* Remove the PID file; return an error if file could not be removed */ static int swtpm_remove_pidfile(struct swtpm *self) { if (self->pidfile && unlink(self->pidfile) < 0 && errno != ENOENT) return 1; return 0; } /* Stop a running swtpm instance and close all the file descriptors connecting to it */ static void swtpm_stop(struct swtpm *self) { unsigned c; gboolean ended = FALSE; if (self->pid > 0) { self->cops->ctrl_shutdown(self); for (c = 0; c < 500; c++) { if (kill(self->pid, 0) < 0) { ended = TRUE; break; } usleep(1000); } if (!ended) kill(self->pid, SIGKILL); waitpid(self->pid, NULL, 0); self->pid = 0; } self->cops->remove_pidfile(self); if (self->ctrl_fds[0] >= 0) { close(self->ctrl_fds[0]); close(self->ctrl_fds[1]); self->ctrl_fds[0] = self->ctrl_fds[1] = -1; } if (self->data_fds[0] >= 0) { close(self->data_fds[0]); close(self->data_fds[1]); self->data_fds[0] = self->data_fds[1] = -1; } } /* Destroy a running swtpm instance */ static void swtpm_destroy(struct swtpm *self) { self->cops->stop(self); } /* Send a command to swtpm and receive the response either via control or data channel */ static int transfer(struct swtpm *self, void *buffer, size_t buffer_len, const char *cmdname, gboolean use_ctrl, void *respbuffer, size_t *respbuffer_len) { size_t offset; int sockfd; ssize_t n; unsigned char resp[4096]; ssize_t resplen; uint32_t returncode; if (use_ctrl) { sockfd = self->ctrl_fds[0]; offset = 0; } else { sockfd = self->data_fds[0]; offset = 6; } n = write(sockfd, buffer, buffer_len); if (n < 0) { logerr(self->logfile, "Could not send %s buffer to swtpm: %s\n", cmdname, strerror(errno)); return 1; } if ((size_t)n != buffer_len) { logerr(self->logfile, "Could not send all bytes to swtpm: %zu < %zu\n", (size_t)n, buffer_len); return 1; } resplen = read(sockfd, resp, sizeof(resp)); if (resplen < 0) { logerr(self->logfile, "Could not receive response to %s from swtpm: %s\n", cmdname, strerror(errno)); return 1; } if (!use_ctrl) { if ((size_t)resplen < sizeof(struct tpm_resp_header)) { logerr(self->logfile, "Response for %s has only %d bytes.\n", cmdname, resplen); return 1; } } else if ((size_t)resplen < 4) { logerr(self->logfile, "Response for %s has only %d bytes.\n", cmdname, resplen); return 1; } memcpy(&returncode, &resp[offset], sizeof(returncode)); returncode = be32toh(returncode); if (returncode != 0) { logerr(self->logfile, "%s failed: 0x%x\n", cmdname, returncode); return 1; } if (respbuffer) { *respbuffer_len = min((size_t)resplen, *respbuffer_len); memcpy(respbuffer, resp, *respbuffer_len); } return 0; } /* Send a CMD_SHUTDOWN over the control channel */ static int swtpm_ctrl_shutdown(struct swtpm *self) { uint32_t cmd = htobe32(CMD_SHUTDOWN); return transfer(self, &cmd, sizeof(cmd), "CMD_SHUTDOWN", TRUE, NULL, 0); } /* Get the TPM specification parameters over the control channel */ static int swtpm_ctrl_get_tpm_specs_and_attrs(struct swtpm *self, gchar **result) { unsigned char req[] = {AS4BE(CMD_GET_INFO), AS8BE(SWTPM_INFO_TPMSPECIFICATION | SWTPM_INFO_TPMATTRIBUTES), AS4BE(0), AS4BE(0)}; unsigned char tpmresp[1024]; size_t tpmresp_len = sizeof(tpmresp); int ret; uint32_t length; ret = transfer(self, req, sizeof(req), "CMD_GET_INFO", TRUE, tpmresp, &tpmresp_len); if (ret != 0) return 1; if (tpmresp_len < 8 + sizeof(length)) goto err_too_short; memcpy(&length, &tpmresp[8], sizeof(length)); length = htobe32(length); if (tpmresp_len < 12 + length) goto err_too_short; *result = g_strndup((gchar *)&tpmresp[12], length); return 0; err_too_short: logerr(self->logfile, "Response from CMD_GET_INFO is too short!\n"); return 1; } static const struct swtpm_cops swtpm_cops = { .start = swtpm_start, .stop = swtpm_stop, .destroy = swtpm_destroy, .remove_pidfile = swtpm_remove_pidfile, .ctrl_shutdown = swtpm_ctrl_shutdown, .ctrl_get_tpm_specs_and_attrs = swtpm_ctrl_get_tpm_specs_and_attrs, }; /* * TPM 2 support */ #define TPM2_ST_NO_SESSIONS 0x8001 #define TPM2_ST_SESSIONS 0x8002 #define TPM2_CC_EVICTCONTROL 0x00000120 #define TPM2_CC_NV_DEFINESPACE 0x0000012a #define TPM2_CC_PCR_ALLOCATE 0x0000012b #define TPM2_CC_CREATEPRIMARY 0x00000131 #define TPM2_CC_NV_WRITE 0x00000137 #define TPM2_CC_NV_WRITELOCK 0x00000138 #define TPM2_CC_SHUTDOWN 0x00000145 #define TPM2_CC_GETCAPABILITY 0x0000017a #define TPM2_SU_CLEAR 0x0000 #define TPM2_RH_OWNER 0x40000001 #define TPM2_RS_PW 0x40000009 #define TPM2_RH_ENDORSEMENT 0x4000000b #define TPM2_RH_PLATFORM 0x4000000c #define TPM2_ALG_RSA 0x0001 #define TPM2_ALG_SHA1 0x0004 #define TPM2_ALG_AES 0x0006 #define TPM2_ALG_SHA256 0x000b #define TPM2_ALG_SHA384 0x000c #define TPM2_ALG_SHA512 0x000d #define TPM2_ALG_SHA3_256 0x0027 #define TPM2_ALG_SHA3_384 0x0028 #define TPM2_ALG_SHA3_512 0x0029 #define TPM2_ALG_NULL 0x0010 #define TPM2_ALG_SM3 0x0012 #define TPM2_ALG_ECC 0x0023 #define TPM2_ALG_CFB 0x0043 #define TPM2_CAP_PCRS 0x00000005 #define TPM2_ECC_NIST_P384 0x0004 #define TPMA_NV_PLATFORMCREATE 0x40000000 #define TPMA_NV_AUTHREAD 0x40000 #define TPMA_NV_NO_DA 0x2000000 #define TPMA_NV_PPWRITE 0x1 #define TPMA_NV_PPREAD 0x10000 #define TPMA_NV_OWNERREAD 0x20000 #define TPMA_NV_WRITEDEFINE 0x2000 // Use standard EK Cert NVRAM, EK and SRK handles per IWG spec. // "TCG TPM v2.0 Provisioning Guide"; Version 1.0, Rev 1.0, March 15, 2017 // Table 2 #define TPM2_NV_INDEX_RSA2048_EKCERT 0x01c00002 #define TPM2_NV_INDEX_RSA2048_EKTEMPLATE 0x01c00004 #define TPM2_NV_INDEX_RSA3072_HI_EKCERT 0x01c0001c #define TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE 0x01c0001d // For ECC follow "TCG EK Credential Profile For TPM Family 2.0; Level 0" // Specification Version 2.1; Revision 13; 10 December 2018 #define TPM2_NV_INDEX_PLATFORMCERT 0x01c08000 #define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT 0x01c00016 #define TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE 0x01c00017 #define TPM2_EK_RSA_HANDLE 0x81010001 #define TPM2_EK_RSA3072_HANDLE 0x8101001c #define TPM2_EK_ECC_SECP384R1_HANDLE 0x81010016 #define TPM2_SPK_HANDLE 0x81000001 #define TPM_REQ_HEADER_INITIALIZER(TAG, SIZE, ORD) \ { \ .tag = htobe16(TAG), \ .size = htobe32(SIZE), \ .ordinal = htobe32(ORD), \ } struct tpm2_authblock { uint32_t auth; uint16_t foo; // FIXME uint8_t continueSession; uint16_t bar; // FIMXE } __attribute__((packed)); #define TPM2_AUTHBLOCK_INITIALIZER(AUTH, FOO, CS, BAR) \ { \ .auth = htobe32(AUTH), \ .foo = htobe16(FOO), \ .continueSession = CS, \ .bar = htobe16(BAR), \ } static const unsigned char NONCE_EMPTY[2] = {AS2BE(0)}; static const unsigned char NONCE_RSA2048[2+0x100] = {AS2BE(0x100), 0, }; static const unsigned char NONCE_RSA3072[2+0x180] = {AS2BE(0x180), 0, }; static const unsigned char NONCE_ECC_384[2+0x30] = {AS2BE(0x30), 0, }; static const struct bank_to_name { uint16_t hashAlg; const char *name; } banks_to_names[] = { {TPM2_ALG_SHA1, "sha1"}, {TPM2_ALG_SHA256, "sha256"}, {TPM2_ALG_SHA384, "sha384"}, {TPM2_ALG_SHA512, "sha512"}, {TPM2_ALG_SM3, "sm3-256"}, {TPM2_ALG_SHA3_256, "sha3-256"}, {TPM2_ALG_SHA3_384, "sha3-384"}, {TPM2_ALG_SHA3_512, "sha3-512"}, {0, NULL}, }; /* function prototypes */ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags, const unsigned char *symkeydata, size_t symkeydata_len, const unsigned char *authpolicy, size_t authpolicy_len, unsigned int rsa_keysize, gboolean havenonce, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, gchar **ekparam); static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs, const unsigned char *data, size_t data_len, gboolean lock_nvram, const char *purpose); /* Given a hash algo identifier, return the name of the hash bank */ static const char *get_name_for_bank(uint16_t hashAlg) { size_t i; for (i = 0; banks_to_names[i].name; i++) { if (banks_to_names[i].hashAlg == hashAlg) return banks_to_names[i].name; } return NULL; } /* Give the name of a hash bank, return its algo identifer */ static uint16_t get_hashalg_by_bankname(const char *name) { size_t i; for (i = 0; banks_to_names[i].name; i++) { if (strcmp(banks_to_names[i].name, name) == 0) return banks_to_names[i].hashAlg; } return 0; } /* Do an SU_CLEAR shutdown of the TPM 2 */ static int swtpm_tpm2_shutdown(struct swtpm *self) { struct tpm2_shutdown_req { struct tpm_req_header hdr; uint16_t shutdownType; } __attribute__((packed)) req = { .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, sizeof(req), TPM2_CC_SHUTDOWN), .shutdownType = htobe16(TPM2_SU_CLEAR) }; return transfer(self, &req, sizeof(req), "TPM2_Shutdown", FALSE, NULL, NULL); } /* Get all available PCR banks */ static int swtpm_tpm2_get_all_pcr_banks(struct swtpm *self, gchar ***all_pcr_banks) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_NO_SESSIONS, 0, TPM2_CC_GETCAPABILITY); g_autofree unsigned char *req = NULL; ssize_t req_len; unsigned char tpmresp[256]; size_t tpmresp_len = sizeof(tpmresp); uint16_t count, bank; const char *name; uint8_t length; size_t offset; size_t i; int ret; req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){AS4BE(TPM2_CAP_PCRS), AS4BE(0), AS4BE(64)}, (size_t)12, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); ret = transfer(self, req, req_len, "TPM2_GetCapability", FALSE, tpmresp, &tpmresp_len); if (ret != 0) return 1; if (tpmresp_len < 17 + sizeof(count)) goto err_too_short; memcpy(&count, &tpmresp[17], sizeof(count)); count = be16toh(count); *all_pcr_banks = g_malloc0(sizeof(char *) * (count + 1)); offset = 19; for (i = 0; i < count; i++) { gchar *n; if (tpmresp_len < offset + sizeof(bank)) goto err_too_short; memcpy(&bank, &tpmresp[offset], sizeof(bank)); bank = be16toh(bank); if (tpmresp_len < offset + 2 + sizeof(length)) goto err_too_short; length = tpmresp[offset + 2]; name = get_name_for_bank(bank); if (name != NULL) n = g_strdup(name); else n = g_strdup_printf("%02x", bank); (*all_pcr_banks)[i] = n; offset += 2 + 1 + length; } return 0; err_too_short: logerr(self->logfile, "Response from TPM2_GetCapability is too short!\n"); return 1; } /* Activate all user-chosen PCR banks and deactivate all others */ static int swtpm_tpm2_set_active_pcr_banks(struct swtpm *self, gchar **pcr_banks, gchar **all_pcr_banks, gchar ***active) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_PCR_ALLOCATE); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); unsigned char pcrselects[6 * 10]; // supports up to 10 PCR banks ssize_t pcrselects_len = 0; size_t count = 0; size_t idx, j; uint16_t hashAlg; g_autofree unsigned char *req = NULL; ssize_t req_len, len; int ret; uint64_t activated_mask = 0; for (idx = 0; pcr_banks[idx] != NULL; idx++) ; *active = g_malloc0(sizeof(char *) * (idx + 1)); for (idx = 0; pcr_banks[idx] != NULL; idx++) { hashAlg = 0; // Is user-chosen pcr_banks[idx] available? for (j = 0; all_pcr_banks[j] != NULL; j++) { if (strcmp(pcr_banks[idx], all_pcr_banks[j]) == 0) { hashAlg = get_hashalg_by_bankname(pcr_banks[idx]); break; } } if (hashAlg != 0 && (activated_mask & (1 << j)) == 0) { (*active)[count] = g_strdup(pcr_banks[idx]); len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len, (unsigned char[]){AS2BE(hashAlg), 3, 0xff, 0xff, 0xff} , (size_t)6, NULL); if (len < 0) { logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__); return 1; } pcrselects_len += len; count++; activated_mask |= (1 << j); } } if (count == 0) { logerr(self->logfile, "No PCR banks could be allocated. None of the selected algorithms are supported.\n"); goto error; } // disable all the other ones not chosen by the user for (idx = 0; all_pcr_banks[idx] != NULL; idx++) { gboolean found = FALSE; for (j = 0; pcr_banks[j] != NULL; j++) { if (strcmp(pcr_banks[j], all_pcr_banks[idx]) == 0) { found = TRUE; break; } } if (found) continue; /* not found, so not chosen by user */ hashAlg = get_hashalg_by_bankname(all_pcr_banks[idx]); len = concat(&pcrselects[pcrselects_len], sizeof(pcrselects) - pcrselects_len, (unsigned char[]){AS2BE(hashAlg), 3, 0, 0, 0}, (size_t)6, NULL); if (len < 0) { logerr(self->logfile, "Internal error in %s: pcrselects is too small\n", __func__); goto error; } pcrselects_len += len; count++; } req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){ AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock)) }, (size_t)8, &authblock, sizeof(authblock), (unsigned char[]){AS4BE(count)}, (size_t)4, pcrselects, pcrselects_len, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: req is too small\n", __func__); goto error; } ((struct tpm_req_header *)req)->size = htobe32(req_len); ret = transfer(self, req, req_len, "TPM2_PCR_Allocate", FALSE, NULL, 0); if (ret != 0) goto error; return 0; error: g_strfreev(*active); *active = NULL; return 1; } /* Make object at the curr_handler permanent with the perm_handle */ static int swtpm_tpm2_evictcontrol(struct swtpm *self, uint32_t curr_handle, uint32_t perm_handle) { struct tpm2_evictcontrol_req { struct tpm_req_header hdr; uint32_t auth; uint32_t objectHandle; uint32_t authblockLen; struct tpm2_authblock authblock; uint32_t persistentHandle; } __attribute__((packed)) req = { .hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, sizeof(req), TPM2_CC_EVICTCONTROL), .auth = htobe32(TPM2_RH_OWNER), .objectHandle = htobe32(curr_handle), .authblockLen = htobe32(sizeof(req.authblock)), .authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0), .persistentHandle = htobe32(perm_handle), }; return transfer(self, &req, sizeof(req), "TPM2_EvictControl", FALSE, NULL, 0); } /* Create an RSA EK */ static int swtpm_tpm2_createprimary_ek_rsa(struct swtpm *self, unsigned int rsa_keysize, gboolean allowsigning, gboolean decryption, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, gchar **ekparam) { unsigned char authpolicy[48]; size_t authpolicy_len; unsigned char symkeydata[6]; size_t symkeydata_len; unsigned int keyflags; unsigned int symkeylen; gboolean havenonce; size_t addlen, off; if (rsa_keysize == 2048) { authpolicy_len = 32; memcpy(authpolicy, (unsigned char []){ 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa }, authpolicy_len); keyflags = 0; symkeylen = 128; havenonce = TRUE; addlen = 0; } else if (rsa_keysize == 3072) { authpolicy_len = 48; memcpy(authpolicy, (unsigned char []){ 0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC, 0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4, 0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09, 0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12 }, authpolicy_len); keyflags = 0x40; symkeylen = 256; havenonce = FALSE; addlen = 16; } else { logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n", __func__, rsa_keysize); return 1; } if (allowsigning && decryption) { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // adminWithPolicy, sign, decrypt keyflags |= 0x000600b2; // symmetric: TPM_ALG_NULL symkeydata_len = 2; memcpy(symkeydata, (unsigned char[]) {AS2BE(TPM2_ALG_NULL)}, symkeydata_len); off = 72 + addlen; } else if (allowsigning) { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // adminWithPolicy, sign keyflags |= 0x000400b2; // symmetric: TPM_ALG_NULL symkeydata_len = 2; memcpy(symkeydata, (unsigned char[]) {AS2BE(TPM2_ALG_NULL)}, symkeydata_len); off = 72 + addlen; } else { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // adminWithPolicy, restricted, decrypt keyflags |= 0x000300b2; // symmetric: TPM_ALG_AES, 128bit or 256bit, TPM_ALG_CFB symkeydata_len = 6; memcpy(symkeydata, (unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}, symkeydata_len); off = 76 + addlen; } return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_ENDORSEMENT, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, rsa_keysize, havenonce, off, curr_handle, ektemplate, ektemplate_len, ekparam); } /* Create an RSA key with the given parameters */ static int swtpm_tpm2_createprimary_rsa(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags, const unsigned char *symkeydata, size_t symkeydata_len, const unsigned char *authpolicy, size_t authpolicy_len, unsigned int rsa_keysize, gboolean havenonce, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, gchar **ekparam) { const unsigned char *nonce; size_t nonce_len; uint16_t hashalg; struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); g_autofree unsigned char *public = NULL; ssize_t public_len; g_autofree unsigned char *createprimary = NULL; ssize_t createprimary_len; int ret; unsigned char tpmresp[2048]; size_t tpmresp_len = sizeof(tpmresp); uint16_t modlen; if (rsa_keysize == 2048) { nonce = NONCE_RSA2048; nonce_len = sizeof(NONCE_RSA2048); hashalg = TPM2_ALG_SHA256; } else if (rsa_keysize == 3072) { if (!havenonce) { nonce = NONCE_EMPTY; nonce_len = sizeof(NONCE_EMPTY); } else { nonce = NONCE_RSA3072; nonce_len = sizeof(NONCE_RSA3072); } hashalg = TPM2_ALG_SHA384; } else { logerr(self->logfile, "Internal error in %s: unsupported RSA keysize %d.\n", __func__, rsa_keysize); return 1; } public_len = memconcat(&public, (unsigned char[]) { AS2BE(TPM2_ALG_RSA), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len) }, (size_t)10, authpolicy, authpolicy_len, symkeydata, symkeydata_len, (unsigned char[]) { AS2BE(TPM2_ALG_NULL), AS2BE(rsa_keysize), AS4BE(0) }, (size_t)8, nonce, nonce_len, NULL); if (public_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } if (ektemplate) { if (*ektemplate_len < (size_t)public_len) { logerr(self->logfile, "Internal error in %s: Need %zu bytes for ektemplate (rsa) but got only %zu\n", __func__, public_len, *ektemplate_len); return 1; } memcpy(ektemplate, public, public_len); *ektemplate_len = public_len; } createprimary_len = memconcat(&createprimary, &hdr, sizeof(hdr), (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8, &authblock, sizeof(authblock), (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8, public, public_len, (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6, NULL); if (createprimary_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len); ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(RSA)", FALSE, tpmresp, &tpmresp_len); if (ret != 0) return 1; if (curr_handle) { if (tpmresp_len < 10 + sizeof(*curr_handle)) goto err_too_short; memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle)); *curr_handle = be32toh(*curr_handle); } if (tpmresp_len < off + sizeof(modlen)) goto err_too_short; memcpy(&modlen, &tpmresp[off], sizeof(modlen)); modlen = be16toh(modlen); if (modlen != rsa_keysize >> 3) { logerr(self->logfile, "Internal error in %s: Getting modulus from wrong offset %zu\n", __func__, off); return 1; } if (ekparam) { if (tpmresp_len < off + 2 + modlen) goto err_too_short; *ekparam = print_as_hex(&tpmresp[off + 2], modlen); } return 0; err_too_short: logerr(self->logfile, "Response from TPM2_CreatePrimary(RSA) is too short!\n"); return 1; } /* Create an ECC key with the given parameters */ static int swtpm_tpm2_createprimary_ecc(struct swtpm *self, uint32_t primaryhandle, unsigned int keyflags, const unsigned char *symkeydata, size_t symkeydata_len, const unsigned char *authpolicy, size_t authpolicy_len, unsigned short curveid, unsigned short hashalg, const unsigned char *nonce, size_t nonce_len, size_t off, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, gchar **ekparam) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_CREATEPRIMARY); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); g_autofree unsigned char *public = NULL; ssize_t public_len; g_autofree unsigned char *createprimary = NULL; ssize_t createprimary_len; int ret; unsigned char tpmresp[2048]; size_t tpmresp_len = sizeof(tpmresp); size_t off2; uint16_t exp_ksize, ksize1, ksize2; const char *cid; public_len = memconcat(&public, (unsigned char[]){ AS2BE(TPM2_ALG_ECC), AS2BE(hashalg), AS4BE(keyflags), AS2BE(authpolicy_len) }, (size_t)10, authpolicy, authpolicy_len, symkeydata, symkeydata_len, (unsigned char[]) {AS2BE(TPM2_ALG_NULL), AS2BE(curveid), AS2BE(TPM2_ALG_NULL)}, (size_t)6, nonce, nonce_len, nonce, nonce_len, NULL); if (public_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } if (ektemplate) { if (*ektemplate_len < (size_t)public_len) { logerr(self->logfile, "Internal error: Need %zu bytes for ektemplate (ecc) but got only %zu\n", public_len, ektemplate_len); return 1; } memcpy(ektemplate, public, public_len); *ektemplate_len = public_len; } createprimary_len = memconcat(&createprimary, &hdr, sizeof(hdr), (unsigned char[]) {AS4BE(primaryhandle), AS4BE(sizeof(authblock))}, (size_t)8, &authblock, sizeof(authblock), (unsigned char[]) {AS2BE(4), AS4BE(0), AS2BE(public_len)}, (size_t)8, public, public_len, (unsigned char[]) {AS4BE(0), AS2BE(0)}, (size_t)6, NULL); if (createprimary_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)createprimary)->size = htobe32(createprimary_len); ret = transfer(self, createprimary, createprimary_len, "TPM2_CreatePrimary(ECC)", FALSE, tpmresp, &tpmresp_len); if (ret != 0) return 1; if (curr_handle) { if (tpmresp_len < 10 + sizeof(*curr_handle)) goto err_too_short; memcpy(curr_handle, &tpmresp[10], sizeof(*curr_handle)); *curr_handle = be32toh(*curr_handle); } if (curveid == TPM2_ECC_NIST_P384) { exp_ksize = 48; cid = "secp384r1"; } else { logerr(self->logfile, "Unknown curveid 0x%x\n", curveid); return 1; } if (tpmresp_len < off + sizeof(ksize1)) goto err_too_short; memcpy(&ksize1, &tpmresp[off], sizeof(ksize1)); ksize1 = be16toh(ksize1); off2 = off + 2 + ksize1; if (tpmresp_len < off2 + sizeof(ksize2)) goto err_too_short; memcpy(&ksize2, &tpmresp[off2], sizeof(ksize2)); ksize2 = be16toh(ksize2); if (ksize1 != exp_ksize || ksize2 != exp_ksize) { logerr(self->logfile, "ECC: Getting key parameters from wrong offset\n"); return 1; } if (ekparam) { unsigned char *xparam = &tpmresp[off + 2]; unsigned char *yparam = &tpmresp[off2 + 2]; if (tpmresp_len < off + 2 + ksize1 || tpmresp_len < off2 + 2 + ksize2) goto err_too_short; g_autofree gchar *xparam_str = print_as_hex(xparam, ksize1); g_autofree gchar *yparam_str = print_as_hex(yparam, ksize2); *ekparam = g_strdup_printf("x=%s,y=%s,id=%s", xparam_str, yparam_str, cid); } return 0; err_too_short: logerr(self->logfile, "Response from TPM2_CreatePrimary(ECC) is too short!\n"); return 1; } static int swtpm_tpm2_createprimary_spk_ecc_nist_p384(struct swtpm *self, uint32_t *curr_handle) { unsigned int keyflags = 0x00030472; const unsigned char authpolicy[0]; size_t authpolicy_len = sizeof(authpolicy); const unsigned char symkeydata[] = {AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}; size_t symkeydata_len = sizeof(symkeydata); size_t off = 42; return swtpm_tpm2_createprimary_ecc(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384, NONCE_ECC_384, sizeof(NONCE_ECC_384), off, curr_handle, NULL, 0, NULL); } static int swtpm_tpm2_createprimary_spk_rsa(struct swtpm *self, unsigned int rsa_keysize, uint32_t *curr_handle) { unsigned int keyflags = 0x00030472; const unsigned char authpolicy[0]; size_t authpolicy_len = sizeof(authpolicy); unsigned short symkeylen = 0; unsigned char symkeydata[6]; size_t symkeydata_len; size_t off = 44; if (rsa_keysize == 2048) symkeylen = 128; else if (rsa_keysize == 3072) symkeylen = 256; symkeydata_len = 6; memcpy(symkeydata, (unsigned char[]) {AS2BE(TPM2_ALG_AES), AS2BE(symkeylen), AS2BE(TPM2_ALG_CFB)}, symkeydata_len); return swtpm_tpm2_createprimary_rsa(self, TPM2_RH_OWNER, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, rsa_keysize, TRUE, off, curr_handle, NULL, 0, NULL); } /* Create either an ECC or RSA storage primary key */ static int swtpm_tpm2_create_spk(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize) { int ret; uint32_t curr_handle; if (isecc) ret = swtpm_tpm2_createprimary_spk_ecc_nist_p384(self, &curr_handle); else ret = swtpm_tpm2_createprimary_spk_rsa(self, rsa_keysize, &curr_handle); if (ret != 0) return 1; ret = swtpm_tpm2_evictcontrol(self, curr_handle, TPM2_SPK_HANDLE); if (ret == 0) logit(self->logfile, "Successfully created storage primary key with handle 0x%x.\n", TPM2_SPK_HANDLE); return ret; } /* Create an ECC EK key that may be allowed to sign and/or decrypt */ static int swtpm_tpm2_createprimary_ek_ecc_nist_p384(struct swtpm *self, gboolean allowsigning, gboolean decryption, uint32_t *curr_handle, unsigned char *ektemplate, size_t *ektemplate_len, gchar **ekparam) { unsigned char authpolicy[48]= { 0xB2, 0x6E, 0x7D, 0x28, 0xD1, 0x1A, 0x50, 0xBC, 0x53, 0xD8, 0x82, 0xBC, 0xF5, 0xFD, 0x3A, 0x1A, 0x07, 0x41, 0x48, 0xBB, 0x35, 0xD3, 0xB4, 0xE4, 0xCB, 0x1C, 0x0A, 0xD9, 0xBD, 0xE4, 0x19, 0xCA, 0xCB, 0x47, 0xBA, 0x09, 0x69, 0x96, 0x46, 0x15, 0x0F, 0x9F, 0xC0, 0x00, 0xF3, 0xF8, 0x0E, 0x12 }; size_t authpolicy_len = 48; unsigned char symkeydata[6]; size_t symkeydata_len; unsigned int keyflags; size_t off; int ret; if (allowsigning && decryption) { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // userWithAuth, adminWithPolicy, sign, decrypt keyflags = 0x000600f2; // symmetric: TPM_ALG_NULL symkeydata_len = 2; memcpy(symkeydata, (unsigned char[]){AS2BE(TPM2_ALG_NULL)}, symkeydata_len); off = 86; } else if (allowsigning) { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // userWithAuth, adminWithPolicy, sign keyflags = 0x000400f2; // symmetric: TPM_ALG_NULL symkeydata_len = 2; memcpy(symkeydata, (unsigned char[]){AS2BE(TPM2_ALG_NULL)}, symkeydata_len); off = 86; } else { // keyflags: fixedTPM, fixedParent, sensitiveDatOrigin, // userWithAuth, adminWithPolicy, restricted, decrypt keyflags = 0x000300f2; // symmetric: TPM_ALG_AES, 256bit, TPM_ALG_CFB symkeydata_len = 6; memcpy(symkeydata, (unsigned char[]){ AS2BE(TPM2_ALG_AES), AS2BE(256), AS2BE(TPM2_ALG_CFB)}, symkeydata_len); off = 90; } ret = swtpm_tpm2_createprimary_ecc(self, TPM2_RH_ENDORSEMENT, keyflags, symkeydata, symkeydata_len, authpolicy, authpolicy_len, TPM2_ECC_NIST_P384, TPM2_ALG_SHA384, NONCE_EMPTY, sizeof(NONCE_EMPTY), off, curr_handle, ektemplate, ektemplate_len, ekparam); if (ret != 0) logerr(self->logfile, "%s failed\n", __func__); return ret; } /* Create an ECC or RSA EK */ static int swtpm_tpm2_create_ek(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean allowsigning, gboolean decryption, gboolean lock_nvram, gchar **ekparam) { uint32_t tpm2_ek_handle, nvindex, curr_handle; const char *keytype; int ret; unsigned char ektemplate[512]; size_t ektemplate_len = sizeof(ektemplate); if (isecc) { tpm2_ek_handle = TPM2_EK_ECC_SECP384R1_HANDLE; keytype = "ECC"; nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKTEMPLATE; } else { if (rsa_keysize == 2048) { tpm2_ek_handle = TPM2_EK_RSA_HANDLE; keytype = "RSA 2048"; nvindex = TPM2_NV_INDEX_RSA2048_EKTEMPLATE; } else if (rsa_keysize == 3072) { tpm2_ek_handle = TPM2_EK_RSA3072_HANDLE; keytype = "RSA 3072"; nvindex = TPM2_NV_INDEX_RSA3072_HI_EKTEMPLATE; } else { logerr(self->logfile, "Internal error: Unsupported RSA keysize %u.\n", rsa_keysize); return 1; } } if (isecc) ret = swtpm_tpm2_createprimary_ek_ecc_nist_p384(self, allowsigning, decryption, &curr_handle, ektemplate, &ektemplate_len, ekparam); else ret = swtpm_tpm2_createprimary_ek_rsa(self, rsa_keysize, allowsigning, decryption, &curr_handle, ektemplate, &ektemplate_len, ekparam); if (ret == 0) ret = swtpm_tpm2_evictcontrol(self, curr_handle, tpm2_ek_handle); if (ret != 0) { logerr(self->logfile, "create_ek failed: 0x%x\n", ret); return 1; } logit(self->logfile, "Successfully created %s EK with handle 0x%x.\n", keytype, tpm2_ek_handle); if (allowsigning) { uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | \ TPMA_NV_AUTHREAD | \ TPMA_NV_OWNERREAD | \ TPMA_NV_PPREAD | \ TPMA_NV_PPWRITE | \ TPMA_NV_NO_DA | \ TPMA_NV_WRITEDEFINE; ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, ektemplate, ektemplate_len, lock_nvram, "EK template"); if (ret == 0) logit(self->logfile, "Successfully created NVRAM area 0x%x for %s EK template.\n", nvindex, keytype); } return ret; } static int swtpm_tpm2_nvdefinespace(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs, uint16_t data_len) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_DEFINESPACE); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); g_autofree unsigned char *nvpublic = NULL; ssize_t nvpublic_len; g_autofree unsigned char *req = NULL; ssize_t req_len; nvpublic_len = memconcat(&nvpublic, (unsigned char[]){ AS4BE(nvindex), AS2BE(TPM2_ALG_SHA256), AS4BE(nvindexattrs), AS2BE(0), AS2BE(data_len)}, (size_t)14, NULL); if (nvpublic_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){AS4BE(TPM2_RH_PLATFORM), AS4BE(sizeof(authblock))}, (size_t)8, &authblock, sizeof(authblock), (unsigned char[]){AS2BE(0), AS2BE(nvpublic_len)}, (size_t)4, nvpublic, nvpublic_len, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); return transfer(self, req, req_len, "TPM2_NV_DefineSpace", FALSE, NULL, 0); } /* Write the data into the given NVIndex */ static int swtpm_tpm2_nv_write(struct swtpm *self, uint32_t nvindex, const unsigned char *data, size_t data_len) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITE); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); g_autofree unsigned char *req = NULL; ssize_t req_len; size_t offset = 0, txlen; int ret; while (offset < data_len) { txlen = min(data_len - offset, 1024); g_free(req); req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){ AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock)) }, (size_t)12, &authblock, sizeof(authblock), (unsigned char[]){AS2BE(txlen)}, (size_t)2, &data[offset], txlen, (unsigned char[]){AS2BE(offset)}, (size_t)2, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); ret = transfer(self, req, req_len, "TPM2_NV_Write", FALSE, NULL, 0); if (ret != 0) return 1; offset += txlen; } return 0; } static int swtpm_tpm2_nv_writelock(struct swtpm *self, uint32_t nvindex) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM2_ST_SESSIONS, 0, TPM2_CC_NV_WRITELOCK); struct tpm2_authblock authblock = TPM2_AUTHBLOCK_INITIALIZER(TPM2_RS_PW, 0, 0, 0); g_autofree unsigned char *req; ssize_t req_len; req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){ AS4BE(TPM2_RH_PLATFORM), AS4BE(nvindex), AS4BE(sizeof(authblock)) }, (size_t)12, &authblock, sizeof(authblock), NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: memconcat failed\n", __func__); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); return transfer(self, req, req_len, "TPM2_NV_WriteLock", FALSE, NULL, 0); } static int swtpm_tpm2_write_nvram(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs, const unsigned char *data, size_t data_len, gboolean lock_nvram, const char *purpose) { int ret = swtpm_tpm2_nvdefinespace(self, nvindex, nvindexattrs, data_len); if (ret != 0) { logerr(self->logfile, "Could not create NVRAM area 0x%x for %s.\n", nvindex, purpose); return 1; } ret = swtpm_tpm2_nv_write(self, nvindex, data, data_len); if (ret != 0) { logerr(self->logfile, "Could not write %s into NVRAM area 0x%x.\n", purpose, nvindex); return 1; } if (lock_nvram) { ret = swtpm_tpm2_nv_writelock(self, nvindex); if (ret != 0) { logerr(self->logfile, "Could not lock EK template NVRAM area 0x%x.\n", nvindex); return 1; } } return 0; } /* Write the platform certificate into an NVRAM area */ static int swtpm_tpm2_write_ek_cert_nvram(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean lock_nvram, const unsigned char *data, size_t data_len) { uint32_t nvindex = 0; g_autofree gchar *keytype = NULL; uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD | TPMA_NV_PPREAD | TPMA_NV_PPWRITE | TPMA_NV_NO_DA | TPMA_NV_WRITEDEFINE; int ret; if (!isecc) { if (rsa_keysize == 2048) nvindex = TPM2_NV_INDEX_RSA2048_EKCERT; else if (rsa_keysize == 3072) nvindex = TPM2_NV_INDEX_RSA3072_HI_EKCERT; keytype = g_strdup_printf("RSA %d", rsa_keysize); } else { nvindex = TPM2_NV_INDEX_ECC_SECP384R1_HI_EKCERT; keytype = g_strdup("ECC"); } ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram, "EK Certificate"); if (ret == 0) logit(self->logfile, "Successfully created NVRAM area 0x%x for %s EK certificate.\n", nvindex, keytype); else logerr(self->logfile, "Could not create NVRAM area 0x%x for %s EK certificate.\n", nvindex, keytype); return ret; } static int swtpm_tpm2_write_platform_cert_nvram(struct swtpm *self, gboolean lock_nvram, const unsigned char *data, size_t data_len) { uint32_t nvindex = TPM2_NV_INDEX_PLATFORMCERT; uint32_t nvindexattrs = TPMA_NV_PLATFORMCREATE | TPMA_NV_AUTHREAD | TPMA_NV_OWNERREAD | TPMA_NV_PPREAD | TPMA_NV_PPWRITE | TPMA_NV_NO_DA | TPMA_NV_WRITEDEFINE; int ret; ret = swtpm_tpm2_write_nvram(self, nvindex, nvindexattrs, data, data_len, lock_nvram, "Platform Certificate"); if (ret == 0) logit(self->logfile, "Successfully created NVRAM area 0x%x for platform certificate.\n", nvindex); else logerr(self->logfile, "Could not create NVRAM area 0x%x for platform certificate.\n", nvindex); return ret; } static const struct swtpm2_ops swtpm_tpm2_ops = { .shutdown = swtpm_tpm2_shutdown, .create_spk = swtpm_tpm2_create_spk, .create_ek = swtpm_tpm2_create_ek, .get_all_pcr_banks = swtpm_tpm2_get_all_pcr_banks, .set_active_pcr_banks = swtpm_tpm2_set_active_pcr_banks, .write_ek_cert_nvram = swtpm_tpm2_write_ek_cert_nvram, .write_platform_cert_nvram = swtpm_tpm2_write_platform_cert_nvram, }; /* * TPM 1.2 support */ #define TPM_TAG_RQU_COMMAND 0x00c1 #define TPM_TAG_RQU_AUTH1_COMMAND 0x00c2 #define TPM_ORD_OIAP 0x0000000A #define TPM_ORD_TAKE_OWNERSHIP 0x0000000D #define TPM_ORD_PHYSICAL_ENABLE 0x0000006F #define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072 #define TPM_ORD_NV_DEFINE_SPACE 0x000000CC #define TPM_ORD_NV_WRITE_VALUE 0x000000CD #define TSC_ORD_PHYSICAL_PRESENCE 0x4000000A #define TPM_ST_CLEAR 0x0001 #define TPM_PHYSICAL_PRESENCE_CMD_ENABLE 0x0020 #define TPM_PHYSICAL_PRESENCE_PRESENT 0x0008 #define TPM_ALG_RSA 0x00000001 #define TPM_KEY_STORAGE 0x0011 #define TPM_AUTH_ALWAYS 0x01 #define TPM_PID_OWNER 0x0005 #define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003 #define TPM_SS_NONE 0x0001 #define TPM_TAG_PCR_INFO_LONG 0x0006 #define TPM_TAG_NV_ATTRIBUTES 0x0017 #define TPM_TAG_NV_DATA_PUBLIC 0x0018 #define TPM_TAG_KEY12 0x0028 #define TPM_LOC_ZERO 0x01 #define TPM_LOC_ALL 0x1f #define TPM_NV_INDEX_D_BIT 0x10000000 #define TPM_NV_INDEX_EKCERT 0xF000 #define TPM_NV_INDEX_PLATFORMCERT 0xF002 #define TPM_NV_INDEX_LOCK 0xFFFFFFFF #define TPM_NV_PER_OWNERREAD 0x00020000 #define TPM_NV_PER_OWNERWRITE 0x00000002 #define TPM_ET_OWNER 0x02 #define TPM_ET_NV 0x0b #define TPM_KH_EK 0x40000006 static int swtpm_tpm12_tsc_physicalpresence(struct swtpm *self, uint16_t physicalpresence) { struct tpm12_tsc_physicalpresence { struct tpm_req_header hdr; uint16_t pp; } req = { .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TSC_ORD_PHYSICAL_PRESENCE), .pp = htobe16(physicalpresence), }; return transfer(self, &req, sizeof(req), "TSC_PhysicalPresence", FALSE, NULL, NULL); } static int swtpm_tpm12_physical_enable(struct swtpm *self) { struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_ENABLE); return transfer(self, &req, sizeof(req), "TPM_PhysicalEnable", FALSE, NULL, NULL); } static int swtpm_tpm12_physical_set_deactivated(struct swtpm *self, uint8_t state) { struct tpm12_tsc_physical_set_deactivated { struct tpm_req_header hdr; uint8_t state; } req = { .hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_PHYSICAL_SET_DEACTIVATED), .state = state, }; return transfer(self, &req, sizeof(req), "TSC_PhysicalSetDeactivated", FALSE, NULL, NULL); } /* Initialize the TPM1.2 */ static int swtpm_tpm12_run_swtpm_bios(struct swtpm *self) { if (swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_CMD_ENABLE) || swtpm_tpm12_tsc_physicalpresence(self, TPM_PHYSICAL_PRESENCE_PRESENT) || swtpm_tpm12_physical_enable(self) || swtpm_tpm12_physical_set_deactivated(self, 0)) return 1; return 0; } static int swptm_tpm12_create_endorsement_keypair(struct swtpm *self, gchar **pubek, size_t *pubek_len) { unsigned char req[] = { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x78, 0x38, 0xf0, 0x30, 0x81, 0x07, 0x2b, 0x0c, 0xa9, 0x10, 0x98, 0x08, 0xc0, 0x4B, 0x05, 0x11, 0xc9, 0x50, 0x23, 0x52, 0xc4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }; unsigned char tpmresp[512]; size_t tpmresp_len = sizeof(tpmresp); uint32_t length; int ret; ret = transfer(self, &req, sizeof(req), "TPM_CreateEndorsementKeyPair", FALSE, &tpmresp, &tpmresp_len); if (ret != 0) return 1; if (tpmresp_len < 34 + sizeof(length)) goto err_too_short; memcpy(&length, &tpmresp[34], sizeof(length)); length = be32toh(length); if (length != 256) { logerr(self->logfile, "Offset to EK Public key is wrong.\n"); return 1; } *pubek_len = 256; if (tpmresp_len < 38 + *pubek_len) goto err_too_short; *pubek = g_malloc(256); memcpy(*pubek, &tpmresp[38], *pubek_len); return 0; err_too_short: logerr(self->logfile, "Response from TPM_CreateEndorsementKeyPair is too short!\n"); return 1; } /* Create an OIAP session */ static int swtpm_tpm12_oiap(struct swtpm *self, uint32_t *authhandle, unsigned char nonce_even[SHA_DIGEST_LENGTH]) { struct tpm_req_header req = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, sizeof(req), TPM_ORD_OIAP); unsigned char tpmresp[64]; size_t tpmresp_len = sizeof(tpmresp); int ret; ret = transfer(self, &req, sizeof(req), "TPM_OIAP", FALSE, &tpmresp, &tpmresp_len); if (ret != 0) return ret; if (tpmresp_len < 10 + sizeof(*authhandle) || tpmresp_len < 14 + SHA_DIGEST_LENGTH) goto err_too_short; memcpy(authhandle, &tpmresp[10], sizeof(*authhandle)); *authhandle = be32toh(*authhandle); memcpy(nonce_even, &tpmresp[14], SHA_DIGEST_LENGTH); return 0; err_too_short: logerr(self->logfile, "Response from TPM_OIAP is too short!\n"); return 1; } static int swtpm_tpm12_take_ownership(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH], const unsigned char srkpass_digest[SHA_DIGEST_LENGTH], const unsigned char *pubek, size_t pubek_len) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_AUTH1_COMMAND, 0, TPM_ORD_TAKE_OWNERSHIP); EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; BIGNUM *exp = BN_new(); BIGNUM *mod = NULL; RSA *rsakey = RSA_new(); int ret = 1; const EVP_MD *sha1 = EVP_sha1(); g_autofree unsigned char *enc_owner_auth = g_malloc(pubek_len); size_t enc_owner_auth_len = pubek_len; g_autofree unsigned char *enc_srk_auth = g_malloc(pubek_len); size_t enc_srk_auth_len = pubek_len; uint32_t auth_handle; unsigned char nonce_even[SHA_DIGEST_LENGTH]; unsigned char nonce_odd[SHA_DIGEST_LENGTH] = {1, 2, 3, 4, 5, 6, }; g_autofree unsigned char *tpm_rsa_key_parms = NULL; ssize_t tpm_rsa_key_parms_len; g_autofree unsigned char *tpm_key_parms = NULL; ssize_t tpm_key_parms_len; g_autofree unsigned char *tpm_key12 = NULL; ssize_t tpm_key12_len; g_autofree unsigned char *in_auth_setup_params = NULL; ssize_t in_auth_setup_params_len; g_autofree unsigned char *macinput = NULL; ssize_t macinput_len; unsigned char in_param_digest[SHA_DIGEST_LENGTH]; unsigned char owner_auth[SHA_DIGEST_LENGTH]; unsigned int owner_auth_len = sizeof(owner_auth); uint8_t continue_auth_session = 0; unsigned char req[1024]; ssize_t req_len, len; struct tpm_req_header *trh; mod = BN_bin2bn((const unsigned char *)pubek, pubek_len, NULL); if (exp == NULL || mod == NULL || BN_hex2bn(&exp, "10001") == 0) { logerr(self->logfile, "Could not create public RSA key!\n"); goto error_free_bn; } pkey = EVP_PKEY_new(); #if OPENSSL_VERSION_NUMBER < 0x10100000 rsakey->n = mod; rsakey->e = exp; #else if (RSA_set0_key(rsakey, mod, exp, NULL) != 1) { logerr(self->logfile, "Could not create public RSA key!\n"); goto error_free_bn; } #endif if (pkey == NULL || EVP_PKEY_assign_RSA(pkey, rsakey) != 1) { logerr(self->logfile, "Could not create public RSA key!\n"); goto error_free_pkey_and_rsa; } ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == NULL) goto error_free_pkey; if (EVP_PKEY_encrypt_init(ctx) < 1 || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) < 1 || EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, sha1) < 1 || EVP_PKEY_CTX_set_rsa_oaep_md(ctx, sha1) < 1 || EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, strdup("TCPA"), 4) < 1 || EVP_PKEY_encrypt(ctx, enc_owner_auth, &enc_owner_auth_len, ownerpass_digest, SHA_DIGEST_LENGTH) < 1|| EVP_PKEY_encrypt(ctx, enc_srk_auth, &enc_srk_auth_len, srkpass_digest, SHA_DIGEST_LENGTH) < 1) { logerr(self->logfile, "Internal error in %s: encryption failed\n", __func__); goto error; } ret = swtpm_tpm12_oiap(self, &auth_handle, nonce_even); if (ret != 0) goto error; tpm_rsa_key_parms_len = memconcat(&tpm_rsa_key_parms, (unsigned char[]){ AS4BE(2048), AS4BE(2), AS4BE(0) }, (size_t)12, NULL); if (tpm_rsa_key_parms_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); goto error; } tpm_key_parms_len = memconcat(&tpm_key_parms, (unsigned char[]){ AS4BE(TPM_ALG_RSA), AS2BE(TPM_ES_RSAESOAEP_SHA1_MGF1), AS2BE(TPM_SS_NONE), AS4BE(tpm_rsa_key_parms_len)}, (size_t)12, tpm_rsa_key_parms, tpm_rsa_key_parms_len, NULL); if (tpm_key_parms_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); goto error; } tpm_key12_len = memconcat(&tpm_key12, (unsigned char[]){ AS2BE(TPM_TAG_KEY12), AS2BE(0), AS2BE(TPM_KEY_STORAGE), AS4BE(0), TPM_AUTH_ALWAYS }, (size_t)11, tpm_key_parms, tpm_key_parms_len, (unsigned char[]){AS4BE(0), AS4BE(0), AS4BE(0)}, (size_t)12, NULL); if (tpm_key12_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); goto error; } req_len = concat(req, sizeof(req), &hdr, sizeof(hdr), (unsigned char[]){AS2BE(TPM_PID_OWNER), AS4BE(enc_owner_auth_len)}, (size_t)6, enc_owner_auth, enc_owner_auth_len, (unsigned char[]){AS4BE(enc_srk_auth_len)}, (size_t)4, enc_srk_auth, enc_srk_auth_len, tpm_key12, tpm_key12_len, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: req is too small\n"); goto error; } SHA1(&req[6], req_len - 6, in_param_digest); in_auth_setup_params_len = memconcat(&in_auth_setup_params, nonce_even, sizeof(nonce_even), nonce_odd, sizeof(nonce_odd), &continue_auth_session, (size_t)1, NULL); if (in_auth_setup_params_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); goto error; } macinput_len = memconcat(&macinput, in_param_digest, sizeof(in_param_digest), in_auth_setup_params, in_auth_setup_params_len, NULL); if (macinput_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); goto error; } HMAC(sha1, ownerpass_digest, SHA_DIGEST_LENGTH, macinput, macinput_len, owner_auth, &owner_auth_len); len = concat(&req[req_len], sizeof(req) - req_len, (unsigned char[]){AS4BE(auth_handle)}, (size_t)4, nonce_odd, sizeof(nonce_odd), &continue_auth_session, (size_t)1, owner_auth, owner_auth_len, NULL); if (len < 0) { logerr(self->logfile, "Internal error in %s: req is too small\n"); goto error; } req_len += len; trh = (struct tpm_req_header *)req; /* old gcc type-punned pointer */ trh->size = htobe32(req_len); ret = transfer(self, req, req_len, "TPM_TakeOwnership", FALSE, NULL, 0); error: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return ret; error_free_bn: BN_free(exp); BN_free(mod); error_free_pkey_and_rsa: RSA_free(rsakey); error_free_pkey: EVP_PKEY_free(pkey); return 1; } static int swtpm_tpm12_nv_define_space(struct swtpm *self, uint32_t nvindex, uint32_t nvindexattrs, size_t size) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_DEFINE_SPACE); g_autofree unsigned char *pcr_info_short = NULL; ssize_t pcr_info_short_len; g_autofree unsigned char *nv_data_public = NULL; ssize_t nv_data_public_len; g_autofree unsigned char *req = NULL; ssize_t req_len; unsigned char zeroes[SHA_DIGEST_LENGTH] = {0, }; pcr_info_short_len = memconcat(&pcr_info_short, (unsigned char[]){AS2BE(3), 0, 0, 0, TPM_LOC_ALL}, (size_t)6, zeroes, sizeof(zeroes), NULL); if (pcr_info_short_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); return 1; } nv_data_public_len = memconcat(&nv_data_public, (unsigned char[]){ AS2BE(TPM_TAG_NV_DATA_PUBLIC), AS4BE(nvindex) }, (size_t)6, pcr_info_short, pcr_info_short_len, pcr_info_short, pcr_info_short_len, (unsigned char[]){ AS2BE(TPM_TAG_NV_ATTRIBUTES), AS4BE(nvindexattrs), 0, 0, 0, AS4BE(size) }, (size_t)13, NULL); if (nv_data_public_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); return 1; } req_len = memconcat(&req, &hdr, sizeof(hdr), nv_data_public, nv_data_public_len, zeroes, sizeof(zeroes), NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE, NULL, 0); } static int swtpm_tpm12_nv_write_value(struct swtpm *self, uint32_t nvindex, const unsigned char *data, size_t data_len) { struct tpm_req_header hdr = TPM_REQ_HEADER_INITIALIZER(TPM_TAG_RQU_COMMAND, 0, TPM_ORD_NV_WRITE_VALUE); g_autofree unsigned char *req = NULL; ssize_t req_len; req_len = memconcat(&req, &hdr, sizeof(hdr), (unsigned char[]){AS4BE(nvindex), AS4BE(0), AS4BE(data_len)}, (size_t)12, data, data_len, NULL); if (req_len < 0) { logerr(self->logfile, "Internal error in %s: out of memory\n"); return 1; } ((struct tpm_req_header *)req)->size = htobe32(req_len); return transfer(self, req, req_len, "TPM_NV_DefineSpace", FALSE, NULL, 0); } /* Write the EK Certificate into NVRAM */ static int swtpm_tpm12_write_ek_cert_nvram(struct swtpm *self, const unsigned char *data, size_t data_len) { uint32_t nvindex = TPM_NV_INDEX_EKCERT | TPM_NV_INDEX_D_BIT; int ret = swtpm_tpm12_nv_define_space(self, nvindex, TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len); if (ret != 0) return 1; ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len); if (ret != 0) return 1; return 0; } /* Write the Platform Certificate into NVRAM */ static int swtpm_tpm12_write_platform_cert_nvram(struct swtpm *self, const unsigned char *data, size_t data_len) { uint32_t nvindex = TPM_NV_INDEX_PLATFORMCERT | TPM_NV_INDEX_D_BIT; int ret = swtpm_tpm12_nv_define_space(self, nvindex, TPM_NV_PER_OWNERREAD | TPM_NV_PER_OWNERWRITE, data_len); if (ret != 0) return 1; ret = swtpm_tpm12_nv_write_value(self, nvindex, data, data_len); if (ret != 0) return 1; return 0; } static int swtpm_tpm12_nv_lock(struct swtpm *self) { return swtpm_tpm12_nv_define_space(self, TPM_NV_INDEX_LOCK, 0, 0); } static const struct swtpm12_ops swtpm_tpm12_ops = { .run_swtpm_bios = swtpm_tpm12_run_swtpm_bios, .create_endorsement_key_pair = swptm_tpm12_create_endorsement_keypair, .take_ownership = swtpm_tpm12_take_ownership, .write_ek_cert_nvram = swtpm_tpm12_write_ek_cert_nvram, .write_platform_cert_nvram = swtpm_tpm12_write_platform_cert_nvram, .nv_lock = swtpm_tpm12_nv_lock, }; static void swtpm_init(struct swtpm *swtpm, gchar **swtpm_exec_l, const gchar *state_path, const gchar *keyopts, const gchar *logfile, int *fds_to_pass, size_t n_fds_to_pass, gboolean is_tpm2) { swtpm->cops = &swtpm_cops; swtpm->swtpm_exec_l = swtpm_exec_l; swtpm->state_path = state_path; swtpm->keyopts = keyopts; swtpm->logfile = logfile; swtpm->fds_to_pass = fds_to_pass; swtpm->n_fds_to_pass = n_fds_to_pass; swtpm->is_tpm2 = is_tpm2; swtpm->pid = -1; swtpm->ctrl_fds[0] = swtpm->ctrl_fds[1] = -1; swtpm->data_fds[0] = swtpm->data_fds[1] = -1; } struct swtpm12 *swtpm12_new(gchar **swtpm_exec_l, const gchar *state_path, const gchar *keyopts, const gchar *logfile, int *fds_to_pass, size_t n_fds_to_pass) { struct swtpm12 *swtpm12 = g_malloc0(sizeof(struct swtpm12)); swtpm_init(&swtpm12->swtpm, swtpm_exec_l, state_path, keyopts, logfile, fds_to_pass, n_fds_to_pass, FALSE); swtpm12->ops = &swtpm_tpm12_ops; return swtpm12; } struct swtpm2 *swtpm2_new(gchar **swtpm_exec_l, const gchar *state_path, const gchar *keyopts, const gchar *logfile, int *fds_to_pass, size_t n_fds_to_pass) { struct swtpm2 *swtpm2 = g_malloc0(sizeof(struct swtpm2)); swtpm_init(&swtpm2->swtpm, swtpm_exec_l, state_path, keyopts, logfile, fds_to_pass, n_fds_to_pass, TRUE); swtpm2->ops = &swtpm_tpm2_ops; return swtpm2; } void swtpm_free(struct swtpm *swtpm) { if (!swtpm) return; g_free(swtpm->pidfile); g_free(swtpm); } swtpm-0.6.3/src/swtpm_setup/swtpm.h000066400000000000000000000064561421141172300174050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm.h: Header file for swtpm.c * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_SETUP_SWTPM_H #define SWTPM_SETUP_SWTPM_H #include #include struct swtpm; /* common swtpm ops for TPM 1.2 & TPM 2 */ struct swtpm_cops { int (*start)(struct swtpm *); void (*stop)(struct swtpm *); void (*destroy)(struct swtpm *); int (*remove_pidfile)(struct swtpm *); int (*ctrl_shutdown)(struct swtpm *); int (*ctrl_get_tpm_specs_and_attrs)(struct swtpm *, gchar **); }; /* TPM 1.2 specific ops */ struct swtpm12_ops { int (*run_swtpm_bios)(struct swtpm *self); int (*create_endorsement_key_pair)(struct swtpm *, gchar **pubkey, size_t *pubek_len); int (*take_ownership)(struct swtpm *self, const unsigned char ownerpass_digest[SHA_DIGEST_LENGTH], const unsigned char srkpass_digest[SHA_DIGEST_LENGTH], const unsigned char *pubek, size_t pubek_len); int (*write_ek_cert_nvram)(struct swtpm *self, const unsigned char *data, size_t data_len); int (*write_platform_cert_nvram)(struct swtpm *self, const unsigned char *data, size_t data_len); int (*nv_lock)(struct swtpm *self); }; /* TPM 2 specific ops */ struct swtpm2_ops { int (*shutdown)(struct swtpm *); int (*create_spk)(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize); int (*create_ek)(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean allowsigning, gboolean decryption, gboolean lock_nvram, gchar **ekparam); int (*get_all_pcr_banks)(struct swtpm *self, gchar ***all_pcr_banks); int (*set_active_pcr_banks)(struct swtpm *self, gchar **pcr_banks_l, gchar **all_pcr_banks, gchar ***active); int (*write_ek_cert_nvram)(struct swtpm *self, gboolean isecc, unsigned int rsa_keysize, gboolean lock_nvram, const unsigned char *data, size_t data_len); int (*write_platform_cert_nvram)(struct swtpm *self, gboolean lock_nvram, const unsigned char *data, size_t data_len); }; /* common structure for swtpm object */ struct swtpm { const struct swtpm_cops *cops; gchar **swtpm_exec_l; const gchar *state_path; const gchar *keyopts; const gchar *logfile; const int *fds_to_pass; size_t n_fds_to_pass; gboolean is_tpm2; GPid pid; gchar *pidfile; int ctrl_fds[2]; int data_fds[2]; }; struct swtpm12 { struct swtpm swtpm; const struct swtpm12_ops *ops; }; struct swtpm2 { struct swtpm swtpm; const struct swtpm2_ops *ops; }; struct swtpm12 *swtpm12_new(gchar **swtpm_prg_l, const gchar *tpm_state_path, const gchar *swtpm_keyopts, const gchar *logfile, int *fds_to_pass, size_t n_fds_to_pass); struct swtpm2 *swtpm2_new(gchar **swtpm_prg_l, const gchar *tpm_state_path, const gchar *swtpm_keyopts, const gchar *logfile, int *fds_to_pass, size_t n_fds_to_pass); void swtpm_free(struct swtpm *); #endif /* SWTPM_SETUP_SWTPM_H */ swtpm-0.6.3/src/swtpm_setup/swtpm_setup.c000066400000000000000000001446561421141172300206250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup.c: Tool to simulate TPM 1.2 & TPM 2 manufacturing * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "swtpm.h" #include "swtpm_setup_conf.h" #include "swtpm_setup_utils.h" #include "swtpm_utils.h" #include /* default values for passwords */ #define DEFAULT_OWNER_PASSWORD "ooo" #define DEFAULT_SRK_PASSWORD "sss" #define SETUP_CREATE_EK_F 1 #define SETUP_TAKEOWN_F 2 #define SETUP_EK_CERT_F 4 #define SETUP_PLATFORM_CERT_F 8 #define SETUP_LOCK_NVRAM_F 16 #define SETUP_SRKPASS_ZEROS_F 32 #define SETUP_OWNERPASS_ZEROS_F 64 #define SETUP_STATE_OVERWRITE_F 128 #define SETUP_STATE_NOT_OVERWRITE_F 256 #define SETUP_TPM2_F 512 #define SETUP_ALLOW_SIGNING_F 1024 #define SETUP_TPM2_ECC_F 2048 #define SETUP_CREATE_SPK_F 4096 #define SETUP_DISPLAY_RESULTS_F 8192 #define SETUP_DECRYPTION_F 16384 /* default configuration file */ #define SWTPM_SETUP_CONF "swtpm_setup.conf" #define DEFAULT_PCR_BANKS "sha1,sha256" /* Default logging goes to stderr */ gchar *gl_LOGFILE = NULL; #define DEFAULT_RSA_KEYSIZE 2048 static const struct flag_to_certfile { unsigned long flag; const char *filename; const char *type; } flags_to_certfiles[] = { {.flag = SETUP_EK_CERT_F , .filename= "ek.cert", .type = "ek" }, {.flag = SETUP_PLATFORM_CERT_F, .filename = "platform.cert", .type = "platform" }, {.flag = 0, .filename = NULL, .type = NULL}, }; /* initialize the path of the config_file */ static int init(gchar **config_file) { const char *xch = getenv("XDG_CONFIG_HOME"); const char *home = getenv("HOME"); char path[PATH_MAX]; const char *p = NULL; int ret = 0; if (xch != NULL && (p = pathjoin(path, sizeof(path), xch, SWTPM_SETUP_CONF, NULL)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else if (home != NULL && (p = pathjoin(path, sizeof(path), home, ".config", SWTPM_SETUP_CONF)) != NULL && access(p, R_OK) == 0) { /* p is good */ } else { p = pathjoin(path, sizeof(path), G_DIR_SEPARATOR_S, SYSCONFDIR, SWTPM_SETUP_CONF); } *config_file = g_strdup(p); return ret; } /* Get the spec and attributes parameters from swtpm */ static int tpm_get_specs_and_attributes(struct swtpm *swtpm, gchar ***params) { int ret; g_autofree gchar *json = NULL; JsonParser *jp = NULL; GError *error = NULL; JsonReader *jr = NULL; JsonNode *root; static const struct parse_rule { const char *node1; const char *node2; gboolean is_int; const char *optname; } parser_rules[7] = { {"TPMSpecification", "family", FALSE, "--tpm-spec-family"}, {"TPMSpecification", "level", TRUE, "--tpm-spec-level"}, {"TPMSpecification", "revision", TRUE, "--tpm-spec-revision"}, {"TPMAttributes", "manufacturer", FALSE, "--tpm-manufacturer"}, {"TPMAttributes", "model", FALSE, "--tpm-model"}, {"TPMAttributes", "version", FALSE, "--tpm-version"}, {NULL, NULL, FALSE, NULL}, }; size_t idx; ret = swtpm->cops->ctrl_get_tpm_specs_and_attrs(swtpm, &json); if (ret != 0) { logerr(gl_LOGFILE, "Could not get the TPM spec and attribute parameters.\n"); return 1; } jp = json_parser_new(); if (!json_parser_load_from_data(jp, json, -1, &error)) { logerr(gl_LOGFILE, "JSON parser failed: %s\n", error->message); g_error_free(error); goto error; } *params = NULL; root = json_parser_get_root(jp); for (idx = 0; parser_rules[idx].node1 != NULL; idx++) { jr = json_reader_new(root); if (json_reader_read_member(jr, parser_rules[idx].node1) && json_reader_read_member(jr, parser_rules[idx].node2)) { gchar *str; if (parser_rules[idx].is_int) str = g_strdup_printf("%ld", (long)json_reader_get_int_value(jr)); else str = g_strdup(json_reader_get_string_value(jr)); *params = concat_arrays(*params, (gchar*[]){ g_strdup(parser_rules[idx].optname), str, NULL }, TRUE); } else { logerr(gl_LOGFILE, "Could not find [%s][%s] in '%s'\n", parser_rules[idx].node1, parser_rules[idx].node2, json); ret = 1; break; } g_object_unref(jr); jr = NULL; } if (ret) { g_strfreev(*params); *params = NULL; g_object_unref(jr); } error: g_object_unref(jp); return ret; } /* Call an external tool to create the certificates */ static int call_create_certs(unsigned long flags, const gchar *configfile, const gchar *certsdir, const gchar *ekparam, const gchar *vmid, struct swtpm *swtpm) { gchar **config_file_lines = NULL; /* must free */ g_autofree gchar *create_certs_tool = NULL; g_autofree gchar *create_certs_tool_config = NULL; g_autofree gchar *create_certs_tool_options = NULL; g_autofree gchar **cmd = NULL; gchar **params = NULL; /* must free */ g_autofree gchar *prgname = NULL; gboolean success; gint exit_status; size_t idx, j; gchar *s; int ret; ret = tpm_get_specs_and_attributes(swtpm, ¶ms); if (ret != 0) goto error; ret = read_file_lines(configfile, &config_file_lines); if (ret != 0) goto error; create_certs_tool = get_config_value(config_file_lines, "create_certs_tool"); create_certs_tool_config = get_config_value(config_file_lines, "create_certs_tool_config"); create_certs_tool_options = get_config_value(config_file_lines, "create_certs_tool_options"); ret = 0; if (create_certs_tool != NULL) { g_autofree gchar *create_certs_tool_path = g_find_program_in_path(create_certs_tool); if (create_certs_tool_path == NULL) { logerr(gl_LOGFILE, "Could not find %s in PATH.\n", create_certs_tool); ret = 1; goto error; } if (flags & SETUP_TPM2_F) { params = concat_arrays(params, (gchar*[]){ g_strdup("--tpm2"), NULL }, TRUE); } cmd = concat_arrays((gchar*[]) { create_certs_tool_path, "--type", "_", /* '_' must be at index '2' ! */ "--ek", (gchar *)ekparam, "--dir", (gchar *)certsdir, NULL }, NULL, FALSE); if (gl_LOGFILE != NULL) cmd = concat_arrays(cmd, (gchar*[]){"--logfile", (gchar *)gl_LOGFILE, NULL}, TRUE); if (vmid != NULL) cmd = concat_arrays(cmd, (gchar*[]){"--vmid", (gchar *)vmid, NULL}, TRUE); cmd = concat_arrays(cmd, params, TRUE); if (create_certs_tool_config != NULL) cmd = concat_arrays(cmd, (gchar*[]){"--configfile", create_certs_tool_config, NULL}, TRUE); if (create_certs_tool_options != NULL) cmd = concat_arrays(cmd, (gchar*[]){"--optsfile", create_certs_tool_options, NULL}, TRUE); s = g_strrstr(create_certs_tool, G_DIR_SEPARATOR_S); if (s) prgname = strdup(&s[1]); else prgname = strdup(create_certs_tool); for (idx = 0; flags_to_certfiles[idx].filename != NULL; idx++) { if (flags & flags_to_certfiles[idx].flag) { g_autofree gchar *standard_output = NULL; g_autofree gchar *standard_error = NULL; GError *error = NULL; gchar **lines; cmd[2] = (gchar *)flags_to_certfiles[idx].type; /* replaces the "_" above */ s = g_strjoinv(" ", cmd); logit(gl_LOGFILE, " Invoking %s\n", s); g_free(s); success = g_spawn_sync(NULL, cmd, NULL, 0, NULL, NULL, &standard_output, &standard_error, &exit_status, &error); if (!success) { logerr(gl_LOGFILE, "An error occurred running %s: %s\n", create_certs_tool, error->message); g_error_free(error); ret = 1; break; } else if (exit_status != 0) { logerr(gl_LOGFILE, "%s exit with status %d: %s\n", prgname, WEXITSTATUS(exit_status), standard_error); ret = 1; break; } lines = g_strsplit(standard_output, "\n", -1); for (j = 0; lines[j] != NULL; j++) { if (strlen(lines[j]) > 0) logit(gl_LOGFILE, "%s: %s\n", prgname, lines[j]); } g_strfreev(lines); g_free(standard_output); standard_output = NULL; g_free(standard_error); standard_error = NULL; } } } error: g_strfreev(config_file_lines); g_strfreev(params); return ret; } /* Create EK and certificate for a TPM 2 */ static int tpm2_create_ek_and_cert(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *vmid, unsigned int rsa_keysize, struct swtpm2 *swtpm2) { g_autofree gchar *filecontent = NULL; size_t filecontent_len; g_autofree gchar *certfile = NULL; g_autofree gchar *ekparam = NULL; size_t idx; int ret; if (flags & SETUP_CREATE_EK_F) { ret = swtpm2->ops->create_ek(&swtpm2->swtpm, !!(flags & SETUP_TPM2_ECC_F), rsa_keysize, !!(flags & SETUP_ALLOW_SIGNING_F), !!(flags & SETUP_DECRYPTION_F), !!(flags & SETUP_LOCK_NVRAM_F), &ekparam); if (ret != 0) return 1; } if (flags & (SETUP_EK_CERT_F | SETUP_PLATFORM_CERT_F)) { ret = call_create_certs(flags, config_file, certsdir, ekparam, vmid, &swtpm2->swtpm); if (ret != 0) return 1; for (idx = 0; flags_to_certfiles[idx].filename; idx++) { if (flags & flags_to_certfiles[idx].flag) { g_free(certfile); certfile = g_strjoin(G_DIR_SEPARATOR_S, certsdir, flags_to_certfiles[idx].filename, NULL); g_free(filecontent); filecontent = NULL; ret = read_file(certfile, &filecontent, &filecontent_len); if (ret != 0) return 1; if (flags_to_certfiles[idx].flag == SETUP_EK_CERT_F) { ret = swtpm2->ops->write_ek_cert_nvram(&swtpm2->swtpm, !!(flags & SETUP_TPM2_ECC_F), rsa_keysize, !!(flags & SETUP_LOCK_NVRAM_F), (const unsigned char*)filecontent, filecontent_len); } else { ret = swtpm2->ops->write_platform_cert_nvram(&swtpm2->swtpm, !!(flags & SETUP_LOCK_NVRAM_F), (const unsigned char *)filecontent, filecontent_len); } unlink(certfile); if (ret != 0) return 1; } } } return 0; } /* Create endorsement keys and certificates for a TPM 2 */ static int tpm2_create_eks_and_certs(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *vmid, unsigned int rsa_keysize, struct swtpm2 *swtpm2) { int ret; /* 1st key will be RSA */ flags = flags & ~SETUP_TPM2_ECC_F; ret = tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); if (ret != 0) return 1; /* 2nd key will be an ECC; no more platform cert */ flags = (flags & ~SETUP_PLATFORM_CERT_F) | SETUP_TPM2_ECC_F; return tpm2_create_ek_and_cert(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); } /* Simulate manufacturing a TPM 2: create keys and certificates */ static int init_tpm2(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file, const gchar *tpm2_state_path, const gchar *vmid, const gchar *pcr_banks, const gchar *swtpm_keyopt, int *fds_to_pass, size_t n_fds_to_pass, unsigned int rsa_keysize) { g_autofree gchar *certsdir = g_strdup(tpm2_state_path); struct swtpm2 *swtpm2; struct swtpm *swtpm; int ret; swtpm2 = swtpm2_new(swtpm_prg_l, tpm2_state_path, swtpm_keyopt, gl_LOGFILE, fds_to_pass, n_fds_to_pass); if (swtpm2 == NULL) return 1; swtpm = &swtpm2->swtpm; ret = swtpm->cops->start(swtpm); if (ret != 0) { logerr(gl_LOGFILE, "Could not start the TPM 2.\n"); goto error; } if ((flags & SETUP_CREATE_SPK_F)) { ret = swtpm2->ops->create_spk(swtpm, !!(flags & SETUP_TPM2_ECC_F), rsa_keysize); if (ret != 0) goto destroy; } ret = tpm2_create_eks_and_certs(flags, config_file, certsdir, vmid, rsa_keysize, swtpm2); if (ret != 0) goto destroy; if (strcmp(pcr_banks, "-") != 0) { gchar **all_pcr_banks = NULL; ret = swtpm2->ops->get_all_pcr_banks(swtpm, &all_pcr_banks); if (ret == 0) { gchar **active_pcr_banks = NULL; gchar **pcr_banks_l = g_strsplit(pcr_banks, ",", -1); ret = swtpm2->ops->set_active_pcr_banks(swtpm, pcr_banks_l, all_pcr_banks, &active_pcr_banks); g_strfreev(pcr_banks_l); if (ret == 0) { g_autofree gchar *active_pcr_banks_join = g_strjoinv(",", active_pcr_banks); g_autofree gchar *all_pcr_banks_join = g_strjoinv(",", all_pcr_banks); logit(gl_LOGFILE, "Successfully activated PCR banks %s among %s.\n", active_pcr_banks_join, all_pcr_banks_join); } g_strfreev(active_pcr_banks); } g_strfreev(all_pcr_banks); if (ret != 0) goto destroy; } ret = swtpm2->ops->shutdown(swtpm); destroy: swtpm->cops->destroy(swtpm); error: swtpm_free(swtpm); return ret; } /* Create the owner password digest */ static void tpm12_get_ownerpass_digest(unsigned long flags, const gchar *ownerpass, unsigned char ownerpass_digest[SHA_DIGEST_LENGTH]) { const gchar zeros[SHA_DIGEST_LENGTH]= {0, }; size_t len; if (ownerpass == NULL) { if (flags & SETUP_OWNERPASS_ZEROS_F) { ownerpass = zeros; len = sizeof(zeros); } else { ownerpass = DEFAULT_OWNER_PASSWORD; len = strlen(ownerpass); } } else { len = strlen(ownerpass); } SHA1((const unsigned char *)ownerpass, len, ownerpass_digest); } /* Create the SRK password digest */ static void tpm12_get_srkpass_digest(unsigned long flags, const gchar *srkpass, unsigned char srkpass_digest[SHA_DIGEST_LENGTH]) { const gchar zeros[SHA_DIGEST_LENGTH]= {0, }; size_t len; if (srkpass == NULL) { if (flags & SETUP_SRKPASS_ZEROS_F) { srkpass = zeros; len = sizeof(zeros); } else { srkpass = DEFAULT_SRK_PASSWORD; len = strlen(srkpass); } } else { len = strlen(srkpass); } SHA1((const unsigned char *)srkpass, len, srkpass_digest); } /* Take ownership of a TPM 1.2 */ static int tpm12_take_ownership(unsigned long flags, const gchar *ownerpass, const gchar *srkpass, gchar *pubek, size_t pubek_len, struct swtpm12 *swtpm12) { unsigned char ownerpass_digest[SHA_DIGEST_LENGTH]; unsigned char srkpass_digest[SHA_DIGEST_LENGTH]; tpm12_get_ownerpass_digest(flags, ownerpass, ownerpass_digest); tpm12_get_srkpass_digest(flags, srkpass, srkpass_digest); return swtpm12->ops->take_ownership(&swtpm12->swtpm, ownerpass_digest, srkpass_digest, (const unsigned char *)pubek, pubek_len); } /* Create the certificates for a TPM 1.2 */ static int tpm12_create_certs(unsigned long flags, const gchar *config_file, const gchar *certsdir, const gchar *ekparam, const gchar *vmid, struct swtpm12 *swtpm12) { g_autofree gchar *filecontent = NULL; g_autofree gchar *certfile = NULL; gsize filecontent_len; size_t idx; int ret; ret = call_create_certs(flags, config_file, certsdir, ekparam, vmid, &swtpm12->swtpm); if (ret != 0) return 1; for (idx = 0; flags_to_certfiles[idx].filename; idx++) { if (flags & flags_to_certfiles[idx].flag) { g_free(certfile); certfile = g_strjoin(G_DIR_SEPARATOR_S, certsdir, flags_to_certfiles[idx].filename, NULL); g_free(filecontent); filecontent = NULL; ret = read_file(certfile, &filecontent, &filecontent_len); if (ret != 0) return 1; if (flags_to_certfiles[idx].flag == SETUP_EK_CERT_F) { ret = swtpm12->ops->write_ek_cert_nvram(&swtpm12->swtpm, (const unsigned char*)filecontent, filecontent_len); if (ret == 0) logit(gl_LOGFILE, "Successfully created NVRAM area for EK certificate.\n"); } else { ret = swtpm12->ops->write_platform_cert_nvram(&swtpm12->swtpm, (const unsigned char*)filecontent, filecontent_len); if (ret == 0) logit(gl_LOGFILE, "Successfully created NVRAM area for Platform certificate.\n"); } unlink(certfile); if (ret != 0) return 1; } } return 0; } /* Simulate manufacturing a TPM 1.2: create keys and certificate and possibly take ownership */ static int init_tpm(unsigned long flags, gchar **swtpm_prg_l, const gchar *config_file, const gchar *tpm_state_path, const gchar *ownerpass, const gchar *srkpass, const gchar *vmid, const gchar *swtpm_keyopt, int *fds_to_pass, size_t n_fds_to_pass) { g_autofree gchar *certsdir = g_strdup(tpm_state_path); struct swtpm12 *swtpm12; struct swtpm *swtpm; g_autofree gchar *pubek = NULL; size_t pubek_len; int ret = 1; swtpm12 = swtpm12_new(swtpm_prg_l, tpm_state_path, swtpm_keyopt, gl_LOGFILE, fds_to_pass, n_fds_to_pass); if (swtpm12 == NULL) return 1; swtpm = &swtpm12->swtpm; ret = swtpm->cops->start(swtpm); if (ret != 0) { logerr(gl_LOGFILE, "Could not start the TPM 1.2.\n"); goto error; } ret = swtpm12->ops->run_swtpm_bios(swtpm); if (ret != 0) goto destroy; if ((flags & SETUP_CREATE_EK_F)) { ret = swtpm12->ops->create_endorsement_key_pair(swtpm, &pubek, &pubek_len); if (ret != 0) goto destroy; logit(gl_LOGFILE, "Successfully created EK.\n"); /* can only take owernship if created an EK */ if ((flags & SETUP_TAKEOWN_F)) { ret = tpm12_take_ownership(flags, ownerpass, srkpass, pubek, pubek_len, swtpm12); if (ret != 0) goto destroy; logit(gl_LOGFILE, "Successfully took ownership of the TPM.\n"); } /* can only create EK cert if created an EK */ if ((flags & SETUP_EK_CERT_F)) { g_autofree gchar *ekparam = print_as_hex((unsigned char *)pubek, pubek_len); ret = tpm12_create_certs(flags, config_file, certsdir, ekparam, vmid, swtpm12); if (ret != 0) goto destroy; } } if ((flags & SETUP_LOCK_NVRAM_F)) { ret = swtpm12->ops->nv_lock(swtpm); if (ret == 0) logit(gl_LOGFILE, "Successfully locked NVRAM access.\n"); } destroy: swtpm->cops->destroy(swtpm); error: swtpm_free(swtpm); return ret; } /* Check whether we are allowed to overwrite existing state. * This function returns 2 if the state exists but flag is set to not to overwrite it, * 0 in case we can overwrite it, 1 if the state exists. */ static int check_state_overwrite(unsigned int flags, const char *tpm_state_path) { const char *statefile; char path[PATH_MAX]; const char *p = NULL; if (flags & SETUP_TPM2_F) statefile = "tpm2-00.permall"; else statefile = "tpm-00.permall"; p = pathjoin(path, sizeof(path), tpm_state_path, statefile, NULL); if (!p) return 1; if (access(p, R_OK|W_OK) == 0) { if (flags & SETUP_STATE_NOT_OVERWRITE_F) { logit(gl_LOGFILE, "Not overwriting existing state file.\n"); return 2; } if (flags & SETUP_STATE_OVERWRITE_F) return 0; logerr(gl_LOGFILE, "Found existing TPM state file %s.\n", statefile); return 1; } return 0; } /* Delete a TPM 1.2 or TPM 2 statefile tpm-00.permall or tpm2-00.permall. * Return 1 in case the file could not be removed, 0 otherwise. */ static int delete_state(unsigned int flags, const char *tpm_state_path) { const char *statefile; char path[PATH_MAX]; const char *p = NULL; if (flags & SETUP_TPM2_F) statefile = "tpm2-00.permall"; else statefile = "tpm-00.permall"; p = pathjoin(path, sizeof(path), tpm_state_path, statefile, NULL); if (!p) return 1; if (unlink(p) != 0) return 1; return 0; } static void versioninfo(void) { printf("TPM emulator setup tool version %d.%d.%d\n", SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO); } static void usage(const char *prgname, const char *default_config_file) { versioninfo(); printf( "Usage: %s [options]\n" "\n" "The following options are supported:\n" "\n" "--runas : Run this program under the given user's account.\n" "\n" "--tpm-state

: Path to a directory where the TPM's state will be written\n" " into; this is a mandatory argument\n" "\n" "--tpmstate : This is an alias for --tpm-state .\n" "\n" "--tpm \n" " : Path to the TPM executable; this is an optional argument and\n" " by default 'swtpm' in the PATH is used.\n" "\n" "--swtpm_ioctl \n" " : Path to the swtpm_ioctl executable; this is deprecated\n" " argument.\n" "\n" "--tpm2 : Setup a TPM 2; by default a TPM 1.2 is setup.\n" "\n" "--createek : Create the EK; for a TPM 2 an RSA and ECC EK will be\n" " created\n" "\n" "--allow-signing : Create an EK that can be used for signing;\n" " this option requires --tpm2.\n" " Note: Careful, this option will create a non-standard EK!\n" "\n" "--decryption : Create an EK that can be used for key encipherment;\n" " this is the default unless --allow-signing is given;\n" " this option requires --tpm2.\n" "\n" "--ecc : This option allows to create a TPM 2's ECC key as storage\n" " primary key; a TPM 2 always gets an RSA and an ECC EK key.\n" "\n" "--take-ownership : Take ownership; this option implies --createek\n" " --ownerpass \n" " : Provide custom owner password; default is %s\n" " --owner-well-known:\n" " : Use an owner password of 20 zero bytes\n" " --srkpass \n" " : Provide custom SRK password; default is %s\n" " --srk-well-known:\n" " : Use an SRK password of 20 zero bytes\n" "--create-ek-cert : Create an EK certificate; this implies --createek\n" "\n" "--create-platform-cert\n" " : Create a platform certificate; this implies --create-ek-cert\n" "\n" "--create-spk : Create storage primary key; this requires --tpm2\n" "\n" "--lock-nvram : Lock NVRAM access\n" "\n" "--display : At the end display as much info as possible about the\n" " configuration of the TPM\n" "\n" "--config \n" " : Path to configuration file; default is %s\n" "\n" "--logfile \n" " : Path to log file; default is logging to stderr\n" "\n" "--keyfile \n" " : Path to a key file containing the encryption key for the\n" " TPM to encrypt its persistent state with. The content\n" " must be a 32 hex digit number representing a 128bit AES key.\n" " This parameter will be passed to the TPM using\n" " '--key file='.\n" "\n" "--keyfile-fd : Like --keyfile but a file descriptor is given to read the\n" " encryption key from.\n" "\n" "--pwdfile \n" " : Path to a file containing a passphrase from which the\n" " TPM will derive the 128bit AES key. The passphrase can be\n" " 32 bytes long.\n" " This parameter will be passed to the TPM using\n" " '--key pwdfile='.\n" "\n" "--pwdfile-fd : Like --pwdfile but a file descriptor is given to to read\n" " the passphrase from.\n" "\n" "--cipher : The cipher to use; either aes-128-cbc or aes-256-cbc;\n" " the default is aes-128-cbc; the same cipher must be\n" " used on the swtpm command line\n" "\n" "--overwrite : Overwrite existing TPM state by re-initializing it; if this\n" " option is not given, this program will return an error if\n" " existing state is detected\n" "\n" "--not-overwrite : Do not overwrite existing TPM state but silently end\n" "\n" "--pcr-banks \n" " : Set of PCR banks to activate. Provide a comma separated list\n" " like 'sha1,sha256'. '-' to skip and leave all banks active.\n" " Default: %s\n" "\n" "--rsa-keysize \n" " : The RSA key size of the EK key; 3072 bits may be supported\n" " if libtpms supports it.\n" " Default: %u\n" "\n" "--tcsd-system-ps-file \n" " : This option is deprecated and has no effect.\n" "\n" "--print-capabilities\n" " : Print JSON formatted capabilites added after v0.1 and exit.\n" "\n" "--version : Display version and exit\n" "\n" "--help,-h,-? : Display this help screen\n\n", prgname, DEFAULT_OWNER_PASSWORD, DEFAULT_SRK_PASSWORD, default_config_file, DEFAULT_PCR_BANKS, DEFAULT_RSA_KEYSIZE ); } /* Get the support RSA key sizes. * This function returns an array of ints like the following * - [ 1024, 2048, 3072 ] * - [] (empty array, indicating only 2048 bit RSA keys are supported) */ static int get_rsa_keysizes(unsigned long flags, gchar **swtpm_prg_l, unsigned int **keysizes, size_t *n_keysizes) { gboolean success; gchar *standard_output = NULL; int exit_status = 0; GError *error = NULL; int ret = 1; const gchar *needle = "\"rsa-keysize-"; unsigned int keysize; gchar **argv = NULL; char *p; int n; *n_keysizes = 0; if (flags & SETUP_TPM2_F) { gchar *my_argv[] = { "--tpm2", "--print-capabilities", NULL }; argv = concat_arrays(swtpm_prg_l, my_argv, FALSE); success = g_spawn_sync(NULL, argv, NULL, G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &standard_output, NULL, &exit_status, &error); if (!success) { logerr(gl_LOGFILE, "Could not start swtpm '%s': %s\n", swtpm_prg_l[0], error->message); g_error_free(error); goto error; } p = standard_output; /* A crude way of parsing the json output just looking for "rsa-keysize-%u" */ while ((p = g_strstr_len(p, -1, needle)) != NULL) { p += strlen(needle); n = sscanf(p, "%u\"", &keysize); if (n == 1) { *keysizes = g_realloc(*keysizes, (*n_keysizes + 1) * sizeof(unsigned int)); (*keysizes)[*n_keysizes] = keysize; (*n_keysizes)++; } } } ret = 0; error: g_free(argv); g_free(standard_output); return ret; } /* Return the RSA key size capabilities in a NULL-terminated array */ static int get_rsa_keysize_caps(unsigned long flags, gchar **swtpm_prg_l, gchar ***keysize_strs) { unsigned int *keysizes = NULL; size_t n_keysizes = 0; size_t i, j; int ret = get_rsa_keysizes(flags, swtpm_prg_l, &keysizes, &n_keysizes); if (ret) return ret; *keysize_strs = g_malloc0(sizeof(char *) * (n_keysizes + 1)); for (i = 0, j = 0; i < n_keysizes; i++) { if (keysizes[i] >= 2048) (*keysize_strs)[j++] = g_strdup_printf("tpm2-rsa-keysize-%u", keysizes[i]); } g_free(keysizes); return 0; } /* Print teh JSON object of swtpm_setup's capabilities */ static int print_capabilities(char **swtpm_prg_l) { g_autofree gchar *param = g_strdup(""); gchar **keysize_strs = NULL; gchar *tmp; size_t i; int ret = 0; ret = get_rsa_keysize_caps(SETUP_TPM2_F, swtpm_prg_l, &keysize_strs); if (ret) return 1; for (i = 0; keysize_strs[i] != NULL; i++) { tmp = g_strdup_printf("%s, \"%s\"", param, keysize_strs[i]); g_free(param); param = tmp; } printf("{ \"type\": \"swtpm_setup\", " "\"features\": [ \"cmdarg-keyfile-fd\", \"cmdarg-pwdfile-fd\", \"tpm12-not-need-root\"" "%s ] }\n", param); g_strfreev(keysize_strs); return 0; } static int change_process_owner(const char *user) { char *endptr; unsigned long long uid = strtoull(user, &endptr, 10); gid_t gid; struct passwd *passwd; int ret = 1; if (*endptr != '\0') { /* assuming a name */ passwd = getpwnam(user); if (passwd == NULL) { logerr(gl_LOGFILE, "Error: User '%s' does not exist.\n", user); goto error; } if (initgroups(passwd->pw_name, passwd->pw_gid) != 0) { logerr(gl_LOGFILE, "Error: initgroups() failed: %s\n", strerror(errno)); goto error; } gid = passwd->pw_gid; uid = passwd->pw_uid; } else { if (uid > 0xffffffff) { logerr(gl_LOGFILE, "Error: uid %s outside valid range.\n", user); goto error; } gid = (gid_t)uid; } if (setgid(gid) != 0) { logerr(gl_LOGFILE, "Error: setgid(%d) failed: %s\n", gid, strerror(errno)); goto error; } if (setuid(uid) != 0) { logerr(gl_LOGFILE, "Error: setuid(%d) failed: %s\n", uid, strerror(errno)); goto error; } ret = 0; error: return ret; } /* Delete swtpm's state file. Those are the files with suffixes * 'permall', 'volatilestate', and 'savestate'. */ static int delete_swtpm_statefiles(const gchar *tpm_state_path) { GError *error = NULL; GDir *dir = g_dir_open(tpm_state_path, 0, &error); int ret = 1; if (dir == NULL) { logerr(gl_LOGFILE, "%s\n", error->message); g_error_free(error); return 1; } while (1) { const gchar *fn = g_dir_read_name(dir); if (fn == NULL) { if (errno != 0 && errno != ENOENT) { logerr(gl_LOGFILE, "Error getting next filename: %s\n", strerror(errno)); break; } else { ret = 0; break; } } if (g_str_has_suffix(fn, "permall") || g_str_has_suffix(fn, "volatilestate") || g_str_has_suffix(fn, "savestate")) { g_autofree gchar *fullname = g_strjoin(G_DIR_SEPARATOR_S, tpm_state_path, fn, NULL); if (unlink(fullname) != 0) { logerr(gl_LOGFILE, "Coud not remove %s: %s\n", fn, strerror(errno)); break; } } } g_dir_close(dir); return ret; } int main(int argc, char *argv[]) { int opt, option_index = 0; const static struct option long_options[] = { {"tpm-state", required_argument, NULL, 't'}, {"tpmstate", required_argument, NULL, 't'}, /* alias for tpm-state */ {"tpm", required_argument, NULL, 'T'}, {"swtpm_ioctl", required_argument, NULL, '_'}, {"tpm2", no_argument, NULL, '2'}, {"ecc", no_argument, NULL, 'e'}, {"createek", no_argument, NULL, 'c'}, {"create-spk", no_argument, NULL, 'C'}, {"take-ownership", no_argument, NULL, 'o'}, {"ownerpass", required_argument, NULL, 'O'}, {"owner-well-known", no_argument, NULL, 'w'}, {"srkpass", required_argument, NULL, 'S'}, {"srk-well-known", no_argument, NULL, 's'}, {"create-ek-cert", no_argument, NULL, 'E'}, {"create-platform-cert", no_argument, NULL, 'P'}, {"lock-nvram", no_argument, NULL, 'L'}, {"display", no_argument, NULL, 'i'}, {"config", required_argument, NULL, 'f'}, {"vmid", required_argument, NULL, 'm'}, {"keyfile", required_argument, NULL, 'x'}, {"keyfile-fd", required_argument, NULL, 'X'}, {"pwdfile", required_argument, NULL, 'k'}, {"pwdfile-fd", required_argument, NULL, 'K'}, {"cipher", required_argument, NULL, 'p'}, {"runas", required_argument, NULL, 'r'}, {"logfile", required_argument, NULL, 'l'}, {"overwrite", no_argument, NULL, 'v'}, {"not-overwrite", no_argument, NULL, 'V'}, {"allow-signing", no_argument, NULL, 'a'}, {"decryption", no_argument, NULL, 'd'}, {"pcr-banks", required_argument, NULL, 'b'}, {"rsa-keysize", required_argument, NULL, 'A'}, {"tcsd-system-ps-file", required_argument, NULL, 'F'}, {"version", no_argument, NULL, '1'}, {"print-capabilities", no_argument, NULL, 'y'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; unsigned long flags = 0; g_autofree gchar *swtpm_prg = NULL; g_autofree gchar *tpm_state_path = NULL; g_autofree gchar *config_file = NULL; g_autofree gchar *ownerpass = NULL; gboolean got_ownerpass = FALSE; g_autofree gchar *srkpass = NULL; gboolean got_srkpass = FALSE; g_autofree gchar *vmid = NULL; g_autofree gchar *pcr_banks = NULL; gboolean printcapabilities = FALSE; g_autofree gchar *keyfile = NULL; long int keyfile_fd = -1; g_autofree gchar *pwdfile = NULL; long int pwdfile_fd = -1; g_autofree gchar *cipher = g_strdup("aes-128-cbc"); g_autofree gchar *rsa_keysize_str = g_strdup_printf("%d", DEFAULT_RSA_KEYSIZE); unsigned int rsa_keysize; g_autofree gchar *swtpm_keyopt = NULL; g_autofree gchar *runas = NULL; gchar *tmp; gchar **swtpm_prg_l = NULL; gchar **tmp_l = NULL; size_t i, n; struct stat statbuf; const struct passwd *curr_user; struct group *curr_grp; char *endptr; char path[PATH_MAX]; char *p; g_autofree gchar *lockfile = NULL; int fds_to_pass[1] = { -1 }; unsigned n_fds_to_pass = 0; char tmpbuffer[200]; time_t now; struct tm *tm; int ret = 1; if (init(&config_file) < 0) goto error; swtpm_prg = g_find_program_in_path("swtpm"); if (swtpm_prg) { tmp = g_strconcat(swtpm_prg, " socket", NULL); g_free(swtpm_prg); swtpm_prg = tmp; } while ((opt = getopt_long(argc, argv, "h?", long_options, &option_index)) != -1) { switch (opt) { case 't': /* --tpmstate, --tpm-state */ g_free(tpm_state_path); tpm_state_path = g_strdup(optarg); break; case 'T': /* --tpm */ g_free(swtpm_prg); swtpm_prg = g_strdup(optarg); break; case '_': /* --swtpm_ioctl */ fprintf(stdout, "Warning: --swtpm_ioctl is deprecated and has no effect."); break; case '2': /* --tpm2 */ flags |= SETUP_TPM2_F; break; case 'e': /* --ecc */ flags |= SETUP_TPM2_ECC_F; break; case 'c': /* --createek */ flags |= SETUP_CREATE_EK_F; break; case 'C': /* --create-spk */ flags |= SETUP_CREATE_SPK_F; break; case 'o': /* --take-ownership */ flags |= SETUP_CREATE_EK_F | SETUP_TAKEOWN_F; break; case 'O': /* --ownerpass */ g_free(ownerpass); ownerpass = g_strdup(optarg); got_ownerpass = TRUE; break; case 'w': /* --owner-well-known */ flags |= SETUP_OWNERPASS_ZEROS_F; got_ownerpass = TRUE; break; case 'S': /* --srk-pass */ g_free(srkpass); srkpass = g_strdup(optarg); got_srkpass = TRUE; break; case 's': /* --srk-well-known */ flags |= SETUP_SRKPASS_ZEROS_F; got_srkpass = TRUE; break; case 'E': /* --create-ek-cert */ flags |= SETUP_CREATE_EK_F | SETUP_EK_CERT_F; break; case 'P': /* --create-platform-cert */ flags |= SETUP_CREATE_EK_F | SETUP_PLATFORM_CERT_F; break; case 'L': /* --lock-nvram */ flags |= SETUP_LOCK_NVRAM_F; break; case 'i': /* --display */ flags |= SETUP_DISPLAY_RESULTS_F; break; case 'f': /* --config */ g_free(config_file); config_file = g_strdup(optarg); break; case 'm': /* --vmid */ g_free(vmid); vmid = g_strdup(optarg); break; case 'x': /* --keyfile */ g_free(keyfile); keyfile = g_strdup(optarg); break; case 'X': /* --pwdfile-fd' */ keyfile_fd = strtoull(optarg, &endptr, 10); if (*endptr != '\0' && keyfile_fd >= INT_MAX) { fprintf(stderr, "Invalid file descriptor '%s'\n", optarg); goto error; } break; case 'k': /* --pwdfile */ g_free(pwdfile); pwdfile = g_strdup(optarg); break; case 'K': /* --pwdfile-fd' */ pwdfile_fd = strtoull(optarg, &endptr, 10); if (*endptr != '\0' || pwdfile_fd >= INT_MAX) { fprintf(stderr, "Invalid file descriptor '%s'\n", optarg); goto error; } break; case 'p': /* --cipher */ g_free(cipher); cipher = g_strdup(optarg); break; case 'r': /* --runas */ g_free(runas); runas = g_strdup(optarg); break; case 'l': /* --logfile */ g_free(gl_LOGFILE); gl_LOGFILE = g_strdup(optarg); break; case 'v': /* --overwrite */ flags |= SETUP_STATE_OVERWRITE_F; break; case 'V': /* --not-overwrite */ flags |= SETUP_STATE_NOT_OVERWRITE_F; break; case 'a': /* --allow-signing */ flags |= SETUP_ALLOW_SIGNING_F; break; case 'd': /* --decryption */ flags |= SETUP_DECRYPTION_F; break; case 'b': /* --pcr-banks */ tmp = g_strconcat(pcr_banks ? pcr_banks: "", pcr_banks ? "," : "", g_strstrip(optarg), NULL); g_free(pcr_banks); pcr_banks = tmp; break; case 'A': /* --rsa-keysize */ g_free(rsa_keysize_str); rsa_keysize_str = strdup(optarg); break; case 'F': /* --tcsd-system-ps-file */ printf("Warning: --tcsd-system-ps-file is deprecated and has no effect."); break; case '1': /* --version */ versioninfo(); ret = 0; goto error; case 'y': /* --print-capabilities */ printcapabilities = TRUE; break; case '?': case 'h': /* --help */ usage(argv[0], config_file); ret = 0; goto out; default: fprintf(stderr, "Unknown option code %d\n", opt); usage(argv[0], config_file); goto error; } } if (swtpm_prg == NULL) { logerr(gl_LOGFILE, "Default TPM 'swtpm' could not be found and was not provided using --tpm\n."); goto error; } swtpm_prg_l = split_cmdline(swtpm_prg); tmp = g_find_program_in_path(swtpm_prg_l[0]); if (!tmp) { logerr(gl_LOGFILE, "TPM at %s is not an executable.\n", swtpm_prg); goto error; } g_free(tmp); if (printcapabilities) { ret = print_capabilities(swtpm_prg_l); goto out; } if (runas) { ret = change_process_owner(runas); if (ret != 0) goto error; } if (!got_ownerpass) ownerpass = g_strdup(DEFAULT_OWNER_PASSWORD); if (!got_srkpass) srkpass = g_strdup(DEFAULT_SRK_PASSWORD); /* check pcr_banks */ tmp_l = g_strsplit(pcr_banks ? pcr_banks : "", ",", -1); for (i = 0, n = 0; tmp_l[i]; i++) n += strlen(tmp_l[i]); g_strfreev(tmp_l); if (n == 0) pcr_banks = g_strdup(DEFAULT_PCR_BANKS); if (gl_LOGFILE != NULL) { FILE *tmpfile; if (stat(gl_LOGFILE, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK) { fprintf(stderr, "Logfile must not be a symlink.\n"); goto error; } tmpfile = fopen(gl_LOGFILE, "a"); if (tmpfile == NULL) { fprintf(stderr, "Cannot write to logfile %s.\n", gl_LOGFILE); goto error; } fclose(tmpfile); } curr_user = getpwuid(getuid()); // Check tpm_state_path directory and access rights if (tpm_state_path == NULL) { logerr(gl_LOGFILE, "--tpm-state must be provided\n"); goto error; } if (stat(tpm_state_path, &statbuf) != 0 || (statbuf.st_mode & S_IFMT) != S_IFDIR) { logerr(gl_LOGFILE, "User %s cannot access directory %s. Make sure it exists and is a directory.\n", curr_user ? curr_user->pw_name : "", tpm_state_path); goto error; } if (access(tpm_state_path, R_OK) != 0) { logerr(gl_LOGFILE, "Need read rights on directory %s for user %s.\n", tpm_state_path, curr_user ? curr_user->pw_name : ""); goto error; } if (access(tpm_state_path, W_OK) != 0) { logerr(gl_LOGFILE, "Need write rights on directory %s for user %s.\n", tpm_state_path, curr_user ? curr_user->pw_name : ""); goto error; } if (flags & SETUP_TPM2_F) { if (flags & SETUP_TAKEOWN_F) { logerr(gl_LOGFILE, "Taking ownership is not supported for TPM 2.\n"); goto error; } } else { if (flags & SETUP_TPM2_ECC_F) { logerr(gl_LOGFILE, "--ecc requires --tpm2.\n"); goto error; } if (flags & SETUP_CREATE_SPK_F) { logerr(gl_LOGFILE, "--create-spk requires --tpm2.\n"); goto error; } } ret = check_state_overwrite(flags, tpm_state_path); if (ret == 1) { goto error; } else if (ret == 2) { ret = 0; goto out; } ret = delete_swtpm_statefiles(tpm_state_path); if (ret != 0) goto error; p = pathjoin(path, sizeof(path), tpm_state_path, ".lock", NULL); if (!p) goto error; lockfile = g_strdup(p); if (stat(lockfile, &statbuf) == 0 && access(lockfile, R_OK|W_OK) != 0) { logerr(gl_LOGFILE, "User %s cannot read/write lockfile %s.\n", curr_user ? curr_user->pw_name : "", lockfile); goto error; } if (access(config_file, R_OK) != 0) { logerr(gl_LOGFILE, "User %s cannot read config file %s.\n", curr_user ? curr_user->pw_name : "", config_file); goto error; } if (cipher != NULL) { if (strcmp(cipher, "aes-128-cbc") != 0 && strcmp(cipher, "aes-cbc") != 0 && strcmp(cipher, "aes-256-cbc") != 0) { logerr(gl_LOGFILE, "Unsupported cipher %s.\n", cipher); goto error; } tmp = g_strdup_printf(",mode=%s", cipher); g_free(cipher); cipher = tmp; } if (keyfile != NULL) { if (access(keyfile, R_OK) != 0) { logerr(gl_LOGFILE, "User %s cannot read keyfile %s.\n", curr_user ? curr_user->pw_name : "", keyfile); goto error; } swtpm_keyopt = g_strdup_printf("file=%s%s", keyfile, cipher); logit(gl_LOGFILE, " The TPM's state will be encrypted with a provided key.\n"); } else if (pwdfile != NULL) { if (access(pwdfile, R_OK) != 0) { logerr(gl_LOGFILE, "User %s cannot read passphrase file %s.\n", curr_user ? curr_user->pw_name : "", pwdfile); goto error; } swtpm_keyopt = g_strdup_printf("pwdfile=%s%s", pwdfile, cipher); logit(gl_LOGFILE, " The TPM's state will be encrypted using a key derived from a passphrase.\n"); } else if (keyfile_fd >= 0) { fds_to_pass[n_fds_to_pass++] = keyfile_fd; swtpm_keyopt = g_strdup_printf("fd=%ld%s", keyfile_fd, cipher); logit(gl_LOGFILE, " The TPM's state will be encrypted with a provided key (fd).\n"); } else if (pwdfile_fd >= 0) { fds_to_pass[n_fds_to_pass++] = pwdfile_fd; swtpm_keyopt = g_strdup_printf("pwdfd=%ld%s", pwdfile_fd, cipher); logit(gl_LOGFILE, " The TPM's state will be encrypted using a key derived from a passphrase (fd).\n"); } if (strcmp(rsa_keysize_str, "max") == 0) { unsigned int *keysizes = NULL; size_t n_keysizes; ret = get_rsa_keysizes(flags, swtpm_prg_l, &keysizes, &n_keysizes); if (ret) goto error; g_free(rsa_keysize_str); if (n_keysizes > 0) { /* last one is the biggest one */ rsa_keysize_str = g_strdup_printf("%u", keysizes[n_keysizes - 1]); } else { rsa_keysize_str = g_strdup("2048"); } g_free(keysizes); } if (strcmp(rsa_keysize_str, "2048") == 0 || strcmp(rsa_keysize_str, "3072") == 0) { unsigned int *keysizes = NULL; size_t n_keysizes; gboolean found = FALSE; ret = get_rsa_keysizes(flags, swtpm_prg_l, &keysizes, &n_keysizes); if (ret) goto error; rsa_keysize = strtoull(rsa_keysize_str, NULL, 10); for (i = 0; i < n_keysizes && found == FALSE; i++) found = (keysizes[i] == rsa_keysize); if (!found && rsa_keysize != 2048) { logerr(gl_LOGFILE, "%u bit RSA keys are not supported by libtpms.\n", rsa_keysize); goto error; } g_free(keysizes); } else { logit(gl_LOGFILE, "Unsupported RSA key size %s.\n", rsa_keysize_str); goto error; } now = time(NULL); tm = localtime(&now); if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) { logerr(gl_LOGFILE, "Could not format time/date string.\n"); goto error; } curr_grp = getgrgid(getgid()); logit(gl_LOGFILE, "Starting vTPM manufacturing as %s:%s @ %s\n", curr_user ? curr_user->pw_name : "", curr_grp ? curr_grp->gr_name : "", tmpbuffer); if ((flags & SETUP_TPM2_F) == 0) { ret = init_tpm(flags, swtpm_prg_l, config_file, tpm_state_path, ownerpass, srkpass, vmid, swtpm_keyopt, fds_to_pass, n_fds_to_pass); } else { ret = init_tpm2(flags, swtpm_prg_l, config_file, tpm_state_path, vmid, pcr_banks, swtpm_keyopt, fds_to_pass, n_fds_to_pass, rsa_keysize); } if (ret == 0) { logit(gl_LOGFILE, "Successfully authored TPM state.\n"); } else { logerr(gl_LOGFILE, "An error occurred. Authoring the TPM state failed.\n"); delete_state(flags, tpm_state_path); } now = time(NULL); tm = localtime(&now); if (strftime(tmpbuffer, sizeof(tmpbuffer), "%a %d %h %Y %I:%M:%S %p %Z", tm) == 0) { logerr(gl_LOGFILE, "Could not format time/date string.\n"); goto error; } logit(gl_LOGFILE, "Ending vTPM manufacturing @ %s\n", tmpbuffer); out: g_strfreev(swtpm_prg_l); g_free(gl_LOGFILE); exit(ret); error: ret = 1; goto out; } swtpm-0.6.3/src/swtpm_setup/swtpm_setup.h000066400000000000000000000004621421141172300206140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup.h: Header for swtpm_setup.c * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_SETUP_H #define SWTPM_SETUP_H #include extern gchar *gl_LOGFILE; #endif /* SWTPM_SETUP_H */ swtpm-0.6.3/src/swtpm_setup/swtpm_setup_conf.h.in000066400000000000000000000006701421141172300222270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup_conf.h: Compile-time constants * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_SETUP_CONF_H #define SWTPM_SETUP_CONF_H #define SWTPM_VER_MAJOR @SWTPM_VER_MAJOR@ #define SWTPM_VER_MINOR @SWTPM_VER_MINOR@ #define SWTPM_VER_MICRO @SWTPM_VER_MICRO@ #define SYSCONFDIR "@SYSCONFDIR@" #endif /* SWTPM_SETUP_CONF_H */ swtpm-0.6.3/src/swtpm_setup/swtpm_setup_utils.c000066400000000000000000000025321421141172300220270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup_utils.c: Utility functions for swtpm_setup * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #include #include #include "swtpm_setup_utils.h" #include "swtpm_utils.h" /* Get a configuration value given its name */ gchar *get_config_value(gchar **config_file_lines, const gchar *configname) { g_autofree gchar *regex = g_strdup_printf("^%s[[:space:]]*=[[:space:]]*([^#\n]*).*", configname); gchar *result = NULL; regmatch_t pmatch[2]; regex_t preg; size_t idx; if (regcomp(&preg, regex, REG_EXTENDED) != 0) { logerr(gl_LOGFILE, "Internal error: Could not compile regex\n"); return NULL; } for (idx = 0; config_file_lines[idx] != NULL; idx++) { const gchar *line = config_file_lines[idx]; if (regexec(&preg, line, 2, pmatch, 0) == 0) { g_autofree gchar *tmp = NULL; tmp = g_strndup(&line[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); /* coverity: g_strchmop modifies in-place */ tmp = g_strchomp(tmp); result = resolve_string(tmp); break; } } regfree(&preg); return result; } swtpm-0.6.3/src/swtpm_setup/swtpm_setup_utils.h000066400000000000000000000006031421141172300220310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup_utils.h: Header for swtpm_setup_utils.c * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_SETUP_UTILS_H #define SWTPM_SETUP_UTILS_H #include gchar *get_config_value(gchar **config_file_lines, const gchar *configname); #endif /* SWPTM_SETUP_UTILS_H */ swtpm-0.6.3/src/utils/000077500000000000000000000000001421141172300146155ustar00rootroot00000000000000swtpm-0.6.3/src/utils/Makefile.am000066400000000000000000000006641421141172300166570ustar00rootroot00000000000000# # src/utils/Makefile.am # # For the license, see the COPYING file in the root directory. # MY_CFLAGS = @MY_CFLAGS@ MY_LDFLAGS = @MY_LDFLAGS@ noinst_HEADERS = \ swtpm_utils.h noinst_LTLIBRARIES = \ libswtpm_utils.la libswtpm_utils_la_CFLAGS = \ $(MY_CFLAGS) \ $(CFLAGS) \ $(HARDENING_CFLAGS) \ $(GLIB_CFLAGS) libswtpm_utils_la_LDFLAGS = \ $(MY_LDFLAGS) \ $(HARDENING_LDFLAGS) libswtpm_utils_la_SOURCES = \ swtpm_utils.c swtpm-0.6.3/src/utils/swtpm_utils.c000066400000000000000000000237341421141172300173640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * swtpm_setup_utils.c: Utility functions for swtpm_setup et al. * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #include "config.h" #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include "swtpm_utils.h" void append_to_file(const char *pathname, const char *str) { size_t n, len; int fd = open(pathname, O_WRONLY|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP); if (fd >= 0) { len = strlen(str); n = write(fd, str, len); if (n != len) { fprintf(stderr, "Error writing to %s: %s\n", pathname, strerror(errno)); } close(fd); } else { fprintf(stderr, "Error opening file %s: %s\n", pathname, strerror(errno)); } } static void alog(FILE *stream, const char *logfile, const char *fmt, va_list ap) { char *str = NULL; int n; n = vasprintf(&str, fmt, ap); if (n < 0) return; if (logfile == NULL) fprintf(stream, "%s", str); else append_to_file(logfile, str); free(str); } void logit(const char *logfile, const char *fmt, ...) { va_list ap; va_start(ap, fmt); alog(stdout, logfile, fmt, ap); va_end(ap); } void logerr(const char *logfile, const char *fmt, ...) { va_list ap; va_start(ap, fmt); alog(stderr, logfile, fmt, ap); va_end(ap); } /* Join paths of up to 3 parts into a pre-allocated buffer. The last part is optional */ char *pathjoin(char *buffer, size_t bufferlen, const char *p1, const char *p2, const char *p3) { char *res = NULL; int n = snprintf(buffer, bufferlen, "%s%s%s%s%s", p1, G_DIR_SEPARATOR_S, p2, p3 ? G_DIR_SEPARATOR_S : "", p3 ? p3 : ""); if (n < 0) { logerr(gl_LOGFILE, "Error: Could not print into buffer.\n"); } else if ((size_t)n >= bufferlen) { logerr(gl_LOGFILE, "Error: Buffer for path is too small.\n"); } else { res = buffer; } return res; } /* Concatenate two NULL-terminated arrays creating one new one; * This function does not duplicate the memory for the elements. * Either one of the arrays may be NULL. The first array can be freed. */ gchar **concat_arrays(char **arr1, char **arr2, gboolean free_arr1) { size_t n = 0; gchar **res; size_t i; for (i = 0; arr1 != NULL && arr1[i]; i++) n++; for (i = 0; arr2 != NULL && arr2[i]; i++) n++; res = g_malloc0(sizeof(char *) * (n + 1)); for (i = 0, n = 0; arr1 != NULL && arr1[i]; i++) res[n++] = arr1[i]; for (i = 0; arr2 != NULL && arr2[i]; i++) res[n++] = arr2[i]; if (free_arr1 && arr1) g_free(arr1); return res; } /* Concatenate buffers into a given buffer of a given length 'buflen' */ ssize_t concat(unsigned char *buffer, size_t buflen, ...) { va_list ap; ssize_t offset = 0; va_start(ap, buflen); while (1) { size_t len; unsigned char *i = va_arg(ap, unsigned char *); if (i == NULL) break; len = va_arg(ap, size_t); if (offset + len > buflen) { offset = -(offset + len); break; } memcpy(&buffer[offset], i, len); offset += len; } va_end(ap); return offset; } /* Concatenate buffers and allocate a new buffer and return its size */ ssize_t memconcat(unsigned char **buffer, ...) { va_list ap; ssize_t offset = 0; size_t allocated = 128; unsigned char *p; *buffer = g_malloc(allocated); p = *buffer; va_start(ap, buffer); while (1) { size_t len; unsigned char *i = va_arg(ap, unsigned char *); if (i == NULL) break; len = va_arg(ap, size_t); if (offset + len > allocated) { allocated += offset + len; *buffer = g_realloc(*buffer, allocated); p = *buffer; } memcpy(&p[offset], i, len); offset += len; } va_end(ap); return offset; } /* Print an input buffer as hex number */ gchar *print_as_hex(unsigned char *input, size_t input_len) { gchar *out = g_malloc(input_len * 2 + 1); size_t i; for (i = 0; i < input_len; i++) g_snprintf(&out[i * 2], 3, "%02x", input[i]); return out; } /* Split a command line and remove all trailing and leading spaces from all entries and remove * 0-length strings entirely. */ gchar **split_cmdline(const gchar *cmdline) { gchar **result = g_strsplit(cmdline, " ", -1); size_t i, j; for (i = 0, j = 0; result[i] != NULL; i++) { gchar *chomped = g_strchomp(result[i]); if (strlen(chomped) == 0) { g_free(chomped); result[i] = NULL; } else { result[i] = NULL; result[j++] = chomped; } } return result; } /* resolve environment variables in a string */ gchar *resolve_string(const gchar *inp) { char *pe; gchar *result = NULL; gchar *new_res, *tmp; size_t sidx = 0; const gchar *envval; while (1) { gchar *ps = g_strstr_len(&inp[sidx], -1, "${"); if (ps == NULL) { if (sidx == 0) { g_free(result); /* coverity */ return g_strdup(inp); } new_res = g_strconcat(result ? result : "", &inp[sidx], NULL); g_free(result); return new_res; } tmp = g_strndup(&inp[sidx], ps - &inp[sidx]); new_res = g_strconcat(result ? result : "", tmp, NULL); g_free(tmp); g_free(result); result = new_res; pe = g_strstr_len(&ps[2], -1, "}"); if (pe == NULL) { new_res = g_strconcat(result ? result : "", ps, NULL); g_free(result); return new_res; } /* name of environment variable */ tmp = g_strndup(&ps[2], pe - &ps[2]); envval = g_getenv(tmp); new_res = g_strconcat(result ? result : "", envval ? envval : "", NULL); g_free(tmp); g_free(result); result = new_res; sidx = &pe[1] - inp; } } /* Read an entire file */ int read_file(const gchar *filename, gchar **buffer, gsize *buffer_len) { GError *error = NULL; if (!g_file_get_contents(filename, buffer, buffer_len, &error)) { logerr(gl_LOGFILE, "%s\n", error->message); g_error_free(error); return 1; } return 0; } /* Read a file and convert its lines into a NULL-termianted array */ int read_file_lines(const char *filename, gchar ***config_file_lines) { g_autofree gchar *buffer = NULL; gsize buffer_len; size_t start = 0; gchar **array; gsize array_len = 1; /* null-terminated array */ if (read_file(filename, &buffer, &buffer_len) != 0) return 1; array = g_malloc0(sizeof(char *) * array_len); while (start < buffer_len) { size_t off = start; /* search for end-of-string or next newline */ while (off < buffer_len && buffer[off] != '\n') off++; if (off > start) { /* non-empty line */ array = g_realloc(array, sizeof(char *) * (array_len + 1)); array[array_len - 1] = g_strndup(&buffer[start], off - start); array_len++; } start = off + 1; } array[array_len - 1] = NULL; *config_file_lines = array; return 0; } static ssize_t write_to_fd(int fd, const unsigned char *data, size_t data_len) { ssize_t n; n = write(fd, data, data_len); if (n < 0) { logerr(gl_LOGFILE, "Could not write to file: %s\n", strerror(errno)); } else if ((size_t)n != data_len) { logerr(gl_LOGFILE, "Could not write all bytes to the file.\n"); n = -1; } return n; } /* Write to a file with the given name */ int write_file(const gchar *filename, const unsigned char *data, size_t data_len) { ssize_t n; int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH ); if (fd < 0) { logerr(gl_LOGFILE, "Could not open file %s for writing: %s\n", filename, strerror(errno)); return 1; } n = write_to_fd(fd, data, data_len); close(fd); if (n < 0) return 1; return 0; } int write_to_tempfile(gchar **filename, const unsigned char *data, size_t data_len) { GError *error = NULL; int fd = g_file_open_tmp("XXXXXX", filename, &error); ssize_t n; if (error) { logerr(gl_LOGFILE, "Could not create temporary file: %s\n", error->message); g_error_free(error); return 1; } n = write_to_fd(fd, data, data_len); if (n < 0) goto error; n = lseek(fd, 0, SEEK_SET); if (n < 0) { logerr(gl_LOGFILE, "Could not seek(0) on file '%s': %s\n", filename, strerror(errno)); goto error; } return fd; error: close(fd); return -1; } /* replace occurences of 'torep' with 'rep' in a string 'in' */ gchar *str_replace(const char *in, const char *torep, const char *rep) { char *res; const char *s, *b; size_t torep_len; size_t rep_len; size_t ctr = 0; size_t off = 0; if (in == NULL || torep == NULL || rep == NULL) return NULL; torep_len = strlen(torep); if (torep_len == 0) return NULL; rep_len = strlen(rep); s = in; while ((s = strstr(s, torep)) != NULL) { s += torep_len; ctr++; } res = g_malloc(strlen(in) - ctr * torep_len + ctr * rep_len + 1); b = s = in; while ((s = strstr(s, torep)) != NULL) { strncpy(&res[off], b, s - b); off += (s - b); s += torep_len; b = s; strcpy(&res[off], rep); off += rep_len; } strcpy(&res[off], b); return res; } swtpm-0.6.3/src/utils/swtpm_utils.h000066400000000000000000000024451421141172300173650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * utils.h: Header file for utils.c * * Author: Stefan Berger, stefanb@linux.ibm.com * * Copyright (c) IBM Corporation, 2021 */ #ifndef SWTPM_UTILS_H #define SWTPM_UTILS_H #include #define min(X,Y) (X) < (Y) ? (X) : (Y) extern gchar *gl_LOGFILE; void append_to_file(const char *pathname, const char *str); void logit(const char *logfile, const char *fmt, ...); void logerr(const char *logfile, const char *fmt, ...); char *pathjoin(char *buffer, size_t bufferlen, const char *p1, const char *p2, const char *p3); gchar **concat_arrays(char **arr1, char **arr2, gboolean free_arr1); ssize_t concat(unsigned char *buf, size_t buflen, ...); ssize_t memconcat(unsigned char **buffer, ...); gchar *resolve_string(const gchar *inp); gchar *print_as_hex(unsigned char *input, size_t input_len); gchar **split_cmdline(const gchar *cmdline); int read_file(const gchar *filename, gchar **buffer, gsize *buffer_len); int read_file_lines(const char *filename, gchar ***config_file_lines); int write_file(const gchar *filename, const unsigned char *data, size_t data_len); int write_to_tempfile(gchar **filename, const unsigned char *data, size_t data_len); gchar *str_replace(const char *in, const char *torep, const char *rep); #endif /* SWTPM_UTILS_H */ swtpm-0.6.3/swtpm.spec000066400000000000000000000125611421141172300147210ustar00rootroot00000000000000%bcond_without gnutls # Macros needed by SELinux %global selinuxtype targeted %global moduletype contrib %global modulename swtpm Summary: TPM Emulator Name: swtpm Version: 0.6.3 Release: 1%{?dist} License: BSD Url: https://github.com/stefanberger/swtpm Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz BuildRequires: automake BuildRequires: autoconf BuildRequires: libtool BuildRequires: libtpms-devel >= 0.6.0 BuildRequires: glib2-devel BuildRequires: json-glib-devel BuildRequires: gmp-devel BuildRequires: expect BuildRequires: net-tools BuildRequires: openssl-devel BuildRequires: socat BuildRequires: python3-twisted BuildRequires: softhsm BuildRequires: trousers >= 0.3.9 %if %{with gnutls} BuildRequires: gnutls >= 3.1.0 BuildRequires: gnutls-devel BuildRequires: gnutls-utils BuildRequires: libtasn1-devel BuildRequires: libtasn1 %endif BuildRequires: selinux-policy-devel BuildRequires: gcc BuildRequires: libseccomp-devel BuildRequires: tpm2-pkcs11 tpm2-pkcs11-tools tpm2-tools tpm2-abrmd Requires: %{name}-libs = %{version}-%{release} Requires: libtpms >= 0.6.0 %{?selinux_requires} %description TPM emulator built on libtpms providing TPM functionality for QEMU VMs %package libs Summary: Private libraries for swtpm TPM emulators License: BSD %description libs A private library with callback functions for libtpms based swtpm TPM emulator %package devel Summary: Include files for the TPM emulator's CUSE interface for usage by clients License: BSD Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description devel Include files for the TPM emulator's CUSE interface. %package tools Summary: Tools for the TPM emulator License: BSD Requires: swtpm = %{version}-%{release} Requires: trousers >= 0.3.9 bash gnutls-utils %description tools Tools for the TPM emulator from the swtpm package %package tools-pkcs11 Summary: Tools for creating a local CA based on a pkcs11 device License: BSD Requires: swtpm-tools = %{version}-%{release} Requires: tpm2-pkcs11 tpm2-pkcs11-tools tpm2-tools tpm2-abrmd Requires: expect gnutls-utils trousers >= 0.3.9 %description tools-pkcs11 Tools for creating a local CA based on a pkcs11 device %prep %autosetup %build NOCONFIGURE=1 ./autogen.sh %configure \ %if %{with gnutls} --with-gnutls \ %endif --without-cuse %make_build %check make %{?_smp_mflags} check %install %make_install rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/*.{a,la,so} %post for pp in /usr/share/selinux/packages/swtpm.pp \ /usr/share/selinux/packages/swtpm_svirt.pp; do %selinux_modules_install -s %{selinuxtype} ${pp} done %postun if [ $1 -eq 0 ]; then for p in swtpm swtpm_svirt; do %selinux_modules_uninstall -s %{selinuxtype} $p done fi %posttrans %selinux_relabel_post -s %{selinuxtype} %ldconfig_post libs %ldconfig_postun libs %files %license LICENSE %doc README %{_bindir}/swtpm %{_mandir}/man8/swtpm.8* %{_datadir}/selinux/packages/swtpm.pp %{_datadir}/selinux/packages/swtpm_svirt.pp %files libs %license LICENSE %doc README %dir %{_libdir}/%{name} %{_libdir}/%{name}/libswtpm_libtpms.so.0 %{_libdir}/%{name}/libswtpm_libtpms.so.0.0.0 %files devel %dir %{_includedir}/%{name} %{_includedir}/%{name}/*.h %{_mandir}/man3/swtpm_ioctls.3* %files tools %doc README %{_bindir}/swtpm_bios %if %{with gnutls} %{_bindir}/swtpm_cert %endif %{_bindir}/swtpm_setup %{_bindir}/swtpm_ioctl %{_mandir}/man8/swtpm_bios.8* %{_mandir}/man8/swtpm_cert.8* %{_mandir}/man8/swtpm_ioctl.8* %{_mandir}/man8/swtpm-localca.conf.8* %{_mandir}/man8/swtpm-localca.options.8* %{_mandir}/man8/swtpm-localca.8* %{_mandir}/man8/swtpm_setup.8* %{_mandir}/man8/swtpm_setup.conf.8* %{_mandir}/man8/swtpm_setup.sh.8* %config(noreplace) %{_sysconfdir}/swtpm_setup.conf %config(noreplace) %{_sysconfdir}/swtpm-localca.options %config(noreplace) %{_sysconfdir}/swtpm-localca.conf %dir %{_datadir}/swtpm %{_datadir}/swtpm/swtpm-localca %{_datadir}/swtpm/swtpm-create-user-config-files %attr( 750, tss, root) %{_localstatedir}/lib/swtpm-localca %files tools-pkcs11 %{_mandir}/man8/swtpm-create-tpmca.8* %{_datadir}/swtpm/swtpm-create-tpmca %changelog * Mon Mar 07 2022 Stefan Berger - 0.6.3-1.20220225git------- - v0.6.3 release * Fri Feb 18 2022 Stefan Berger - 0.6.2-1.20220218git------- - v0.6.2 release * Mon Sep 20 2021 Stefan Berger - 0.6.1-0.20210917git------- - v0.6.1 release * Mon Jun 7 2021 Stefan Berger - 0.6.0-0.20210607git------- - v0.6.0 release * Wed Oct 7 2020 Stefan Berger - 0.5.0-0.20201007git------- - v0.5.0 release * Fri Aug 28 2020 Stefan Berger - 0.4.0-20200218git------- - v0.4.0 release * Mon Feb 17 2020 Stefan Berger - 0.3.0-20200218git38f36f3 - v0.3.0 release * Fri Jul 19 2019 Stefan Berger - 0.2.0-20190716git817d3a8 - v0.2.0 release * Mon Feb 4 2019 Stefan Berger - 0.1.0-0.20190204git2c25d13 - v0.1.0 release * Mon Sep 17 2018 Stefan Berger - 0.1.0-0.20180918git67d7ea3 - Created initial version of rpm spec files - Version is now 0.1.0 - Bugzilla for this spec: https://bugzilla.redhat.com/show_bug.cgi?id=1611829 swtpm-0.6.3/swtpm.spec.in000066400000000000000000000125741421141172300153320ustar00rootroot00000000000000%bcond_without gnutls # Macros needed by SELinux %global selinuxtype targeted %global moduletype contrib %global modulename swtpm Summary: TPM Emulator Name: swtpm Version: @VERSION@ Release: 1%{?dist} License: BSD Url: https://github.com/stefanberger/swtpm Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz BuildRequires: automake BuildRequires: autoconf BuildRequires: libtool BuildRequires: libtpms-devel >= 0.6.0 BuildRequires: glib2-devel BuildRequires: json-glib-devel BuildRequires: gmp-devel BuildRequires: expect BuildRequires: net-tools BuildRequires: openssl-devel BuildRequires: socat BuildRequires: python3-twisted BuildRequires: softhsm BuildRequires: trousers >= 0.3.9 %if %{with gnutls} BuildRequires: gnutls >= 3.1.0 BuildRequires: gnutls-devel BuildRequires: gnutls-utils BuildRequires: libtasn1-devel BuildRequires: libtasn1 %endif BuildRequires: selinux-policy-devel BuildRequires: gcc BuildRequires: libseccomp-devel BuildRequires: tpm2-pkcs11 tpm2-pkcs11-tools tpm2-tools tpm2-abrmd Requires: %{name}-libs = %{version}-%{release} Requires: libtpms >= 0.6.0 %{?selinux_requires} %description TPM emulator built on libtpms providing TPM functionality for QEMU VMs %package libs Summary: Private libraries for swtpm TPM emulators License: BSD %description libs A private library with callback functions for libtpms based swtpm TPM emulator %package devel Summary: Include files for the TPM emulator's CUSE interface for usage by clients License: BSD Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description devel Include files for the TPM emulator's CUSE interface. %package tools Summary: Tools for the TPM emulator License: BSD Requires: swtpm = %{version}-%{release} Requires: trousers >= 0.3.9 bash gnutls-utils %description tools Tools for the TPM emulator from the swtpm package %package tools-pkcs11 Summary: Tools for creating a local CA based on a pkcs11 device License: BSD Requires: swtpm-tools = %{version}-%{release} Requires: tpm2-pkcs11 tpm2-pkcs11-tools tpm2-tools tpm2-abrmd Requires: expect gnutls-utils trousers >= 0.3.9 %description tools-pkcs11 Tools for creating a local CA based on a pkcs11 device %prep %autosetup %build NOCONFIGURE=1 ./autogen.sh %configure \ %if %{with gnutls} --with-gnutls \ %endif --without-cuse %make_build %check make %{?_smp_mflags} check %install %make_install rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/*.{a,la,so} %post for pp in /usr/share/selinux/packages/swtpm.pp \ /usr/share/selinux/packages/swtpm_svirt.pp; do %selinux_modules_install -s %{selinuxtype} ${pp} done %postun if [ $1 -eq 0 ]; then for p in swtpm swtpm_svirt; do %selinux_modules_uninstall -s %{selinuxtype} $p done fi %posttrans %selinux_relabel_post -s %{selinuxtype} %ldconfig_post libs %ldconfig_postun libs %files %license LICENSE %doc README %{_bindir}/swtpm %{_mandir}/man8/swtpm.8* %{_datadir}/selinux/packages/swtpm.pp %{_datadir}/selinux/packages/swtpm_svirt.pp %files libs %license LICENSE %doc README %dir %{_libdir}/%{name} %{_libdir}/%{name}/libswtpm_libtpms.so.0 %{_libdir}/%{name}/libswtpm_libtpms.so.0.0.0 %files devel %dir %{_includedir}/%{name} %{_includedir}/%{name}/*.h %{_mandir}/man3/swtpm_ioctls.3* %files tools %doc README %{_bindir}/swtpm_bios %if %{with gnutls} %{_bindir}/swtpm_cert %endif %{_bindir}/swtpm_setup %{_bindir}/swtpm_ioctl %{_mandir}/man8/swtpm_bios.8* %{_mandir}/man8/swtpm_cert.8* %{_mandir}/man8/swtpm_ioctl.8* %{_mandir}/man8/swtpm-localca.conf.8* %{_mandir}/man8/swtpm-localca.options.8* %{_mandir}/man8/swtpm-localca.8* %{_mandir}/man8/swtpm_setup.8* %{_mandir}/man8/swtpm_setup.conf.8* %{_mandir}/man8/swtpm_setup.sh.8* %config(noreplace) %{_sysconfdir}/swtpm_setup.conf %config(noreplace) %{_sysconfdir}/swtpm-localca.options %config(noreplace) %{_sysconfdir}/swtpm-localca.conf %dir %{_datadir}/swtpm %{_datadir}/swtpm/swtpm-localca %{_datadir}/swtpm/swtpm-create-user-config-files %attr( 750, @TSS_USER@, root) %{_localstatedir}/lib/swtpm-localca %files tools-pkcs11 %{_mandir}/man8/swtpm-create-tpmca.8* %{_datadir}/swtpm/swtpm-create-tpmca %changelog * Mon Mar 07 2022 Stefan Berger - 0.6.3-1.20220225git------- - v0.6.3 release * Fri Feb 18 2022 Stefan Berger - 0.6.2-1.20220218git------- - v0.6.2 release * Mon Sep 20 2021 Stefan Berger - 0.6.1-0.20210917git------- - v0.6.1 release * Mon Jun 7 2021 Stefan Berger - 0.6.0-0.20210607git------- - v0.6.0 release * Wed Oct 7 2020 Stefan Berger - 0.5.0-0.20201007git------- - v0.5.0 release * Fri Aug 28 2020 Stefan Berger - 0.4.0-20200218git------- - v0.4.0 release * Mon Feb 17 2020 Stefan Berger - 0.3.0-20200218git38f36f3 - v0.3.0 release * Fri Jul 19 2019 Stefan Berger - 0.2.0-20190716git817d3a8 - v0.2.0 release * Mon Feb 4 2019 Stefan Berger - 0.1.0-0.20190204git2c25d13 - v0.1.0 release * Mon Sep 17 2018 Stefan Berger - 0.1.0-0.20180918git67d7ea3 - Created initial version of rpm spec files - Version is now 0.1.0 - Bugzilla for this spec: https://bugzilla.redhat.com/show_bug.cgi?id=1611829 swtpm-0.6.3/tests/000077500000000000000000000000001421141172300140305ustar00rootroot00000000000000swtpm-0.6.3/tests/Makefile.am000066400000000000000000000123251421141172300160670ustar00rootroot00000000000000# # tests/Makefile.am # # For the license, see the LICENSE file in the root directory. # check_PROGRAMS = TESTS_ENVIRONMENT = \ abs_top_testdir=`cd '$(top_srcdir)'/tests; pwd` \ abs_top_builddir=`cd '$(top_builddir)'; pwd` \ abs_top_srcdir=`cd '$(top_srcdir)'; pwd` TESTS = \ test_vtpm_proxy \ test_tpm2_vtpm_proxy if WITH_CHARDEV TESTS += \ test_ctrlchannel2 \ test_ctrlchannel4 \ test_tpm2_ctrlchannel2 endif TESTS += \ test_commandline \ test_ctrlchannel \ test_ctrlchannel3 \ test_encrypted_state \ test_getcap \ test_hashing \ test_hashing2 \ test_init \ test_locality \ test_migration_key \ test_parameters \ test_resume_volatile \ test_save_load_encrypted_state \ test_save_load_state \ test_setbuffersize \ test_volatilestate \ test_swtpm_bios \ test_tpm_probe \ test_tpm12 \ test_wrongorder \ \ test_print_capabilities TESTS += \ test_tpm2_derived_keys \ test_tpm2_encrypted_state \ test_tpm2_init \ test_tpm2_getcap \ test_tpm2_locality \ test_tpm2_hashing \ test_tpm2_hashing2 \ test_tpm2_hashing3 \ test_tpm2_migration_key \ test_tpm2_partial_reads \ test_tpm2_print_capabilities \ test_tpm2_resume_volatile \ test_tpm2_savestate \ test_tpm2_save_load_encrypted_state \ test_tpm2_save_load_state_2 \ test_tpm2_save_load_state_3 \ test_tpm2_save_load_state_da_timeout \ test_tpm2_setbuffersize \ test_tpm2_volatilestate \ test_tpm2_wrongorder \ test_tpm2_probe \ \ test_tpm2_swtpm_bios \ \ test_tpm2_ibmtss2 if WITH_GNUTLS TESTS += \ test_samples_create_tpmca \ test_swtpm_cert \ test_swtpm_setup_create_cert \ test_tpm2_parameters \ test_tpm2_samples_swtpm_localca \ test_tpm2_samples_swtpm_localca_pkcs11 \ test_tpm2_swtpm_cert \ test_tpm2_swtpm_cert_ecc \ test_tpm2_swtpm_setup_create_cert if HAVE_TCSD TESTS += \ test_tpm2_samples_create_tpmca endif endif EXTRA_DIST=$(TESTS) \ swtpm_setup.conf \ common \ create_certs.sh \ data/ecpubek.pem \ data/ecprivek.pem \ data/issuercert.pem \ data/pubek.pem \ data/signkey.pem \ data/signkey-encrypted.pem \ data/keyfile.txt \ data/keyfile256bit.txt \ data/pwdfile.txt \ data/migkey1/tpm2-volatilestate.bin \ data/migkey1/volatilestate.bin \ data/tpmstate1/tpm-00.permall \ data/tpmstate1/tpm-00.volatilestate \ data/tpmstate1/README \ data/tpmstate2/tpm-00.permall \ data/tpmstate2/tpm-00.volatilestate \ data/tpmstate2/pwdfile.txt \ data/tpmstate2/README \ data/tpmstate2b/tpm-00.permall \ data/tpmstate2b/tpm-00.volatilestate \ data/tpmstate2b/pwdfile.txt \ data/tpm2state1/tpm2-00.permall \ data/tpm2state1/tpm2-00.volatilestate \ data/tpm2state2/tpm2-00.permall \ data/tpm2state2/tpm2-00.volatilestate \ data/tpm2state2b/pwdfile.txt \ data/tpm2state2b/tpm2-00.permall \ data/tpm2state2b/tpm2-00.volatilestate \ data/tpm2state2/pwdfile.txt \ data/tpm2state3/hkey.priv \ data/tpm2state3/hkey.pub \ data/tpm2state3/signature.bin \ data/tpm2state3/tpm2-00.permall \ data/tpm2state3c/tpm2-00.volatilestate \ data/tpm2state3c/tpm2-00.permall \ data/tpm2state3d/tpm2-00.volatilestate \ data/tpm2state3d/signature2.bin \ data/tpm2state3d/tpm2-00.permall \ data/tpm2state3b/h81000000.bin \ data/tpm2state3b/h02000000.bin \ data/tpm2state3b/tpm2-00.volatilestate \ data/tpm2state3b/tpm2-00.permall \ data/tpm2state4/tpm2-00.volatilestate \ data/tpm2state4/tpm2-00.permall \ data/tpm2state5/signature.bin \ data/tpm2state5/tpm2-00.permall \ load_vtpm_proxy \ patches/0001-Deactivate-test-cases-accessing-rootcerts.txt.patch \ patches/0002-Implement-powerup-for-swtpm.patch \ patches/0003-Set-CRYPTOLIBRARY-to-openssl.patch \ patches/0004-Store-and-restore-volatile-state-at-every-step.patch \ patches/0005-Disable-tests-related-to-events.patch \ patches/0006-Disable-testing-with-RSA-3072.patch \ patches/0007-Disable-rev155-test-cases.patch \ patches/0008-Disable-x509-test-cases.patch \ patches/0009-Disable-getcapability-TPM_CAP_ACT.patch \ patches/libtpm.patch \ softhsm_setup \ test_clientfds.py \ test_common \ test_cuse \ test_setdatafd.py \ test_swtpm_cert \ _test_encrypted_state \ _test_getcap \ _test_hashing \ _test_hashing2 \ _test_init \ _test_locality \ _test_migration_key \ _test_migration_key_2 \ _test_print_capabilities \ _test_resume_volatile \ _test_save_load_encrypted_state \ _test_save_load_state \ _test_setbuffersize \ _test_swtpm_bios \ _test_tpm_probe \ _test_tpm2_derived_keys \ _test_tpm2_encrypted_state \ _test_tpm2_getcap \ _test_tpm2_hashing \ _test_tpm2_hashing2 \ _test_tpm2_hashing3 \ _test_tpm2_init \ _test_tpm2_locality \ _test_tpm2_migration_key \ _test_tpm2_print_capabilities \ _test_tpm2_probe \ _test_tpm2_resume_volatile \ _test_tpm2_savestate \ _test_tpm2_save_load_encrypted_state \ _test_tpm2_save_load_state_da_timeout \ _test_tpm2_setbuffersize \ _test_tpm2_swtpm_bios \ _test_tpm2_volatilestate \ _test_tpm2_wrongorder \ _test_volatilestate \ _test_wrongorder check-display: @if test -n "$$SWTPM_EXE"; then \ echo "*** Using SWTPM_EXE=$$SWTPM_EXE"; \ fi @if test -n "$$SWTPM_BIOS"; then \ echo "*** Using SWTPM_BIOS=$$SWTPM_BIOS"; \ fi @if test -n "$$SWTPM_IOCTL"; then \ echo "*** Using SWTPM_IOCTL=$$SWTPM_IOCTL"; \ fi @if test -n "$$SWTPM_CERT"; then \ echo "*** Using SWTPM_CERT=$$SWTPM_CERT"; \ fi check: check-am check-display swtpm-0.6.3/tests/Readme.md000066400000000000000000000020171421141172300155470ustar00rootroot00000000000000 This directory contains the swtpm tests. To run the tests you need to build swtpm first and then you can run the tests using the following command line: ``` SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_STORE_VOLATILE=1 SWTPM_TEST_IBMTSS2=1 make check ``` You may omit the environment variables if you don't want to run the more time-consuming tests. `SWTPM_TEST_EXPENSIVE=1` enables the following tests: - test_tpm12 - test_tpm2_ibmtss2 `SWTPM_TEST_STORE_VOLATILE=1` enables storing and restoring of the volatile state at every step of the test_tpm2_ibmtss2 test. This environment variable only has an effect if `SWTPM_TEST_EXPENSIVE=1` is set. `SWTPM_TEST_IBMTSS2=1` enables the following tests - test_tpm2_save_load_state_2 - test_tpm2_save_load_state_3 Some tests require root rights, especially those involving the CUSE TPM and the vTPM proxy device. To run these and all the other ones you can use the following command line: ``` sudo bash -c "SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_STORE_VOLATILE=1 SWTPM_TEST_IBMTSS2=1 make check" ``` swtpm-0.6.3/tests/_test_encrypted_state000077500000000000000000000147461421141172300203650ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-encrypted-state" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate KEY=1234567890abcdef1234567890abcdef BINKEY='\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef' SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} keyfile=${TPM_PATH}/keyfile logfile=${TPM_PATH}/logfile binkeyfile=${TPM_PATH}/binkeyfile echo "$KEY" > ${keyfile} echo -en "$BINKEY" > ${binkeyfile} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --key file=$keyfile,mode=aes-cbc,format=hex,remove \ --log file=$logfile display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_file_gone ${keyfile} 4; then echo "Error: Keyfile $keyfile was not removed by ${SWTPM_INTERFACE} tpm." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." echo "TPM Logfile:" cat $logfile exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Saving the volatile state failed." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi tmp=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -g | cut -d":" -f2) if [ $? -ne 0 ]; then echo "Error: Could not get the configration flags of the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "$tmp" != " 0x1" ]; then echo "Error: Unexpected configuration flags: $tmp; expected 0x1." echo "TPM Logfile:" cat $logfile exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi # Start the TPM again; have the keyfile removed run_swtpm ${SWTPM_INTERFACE} \ --key file=$binkeyfile,mode=aes-cbc,format=binary,remove \ --log file=$logfile display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_file_gone ${binkeyfile} 4; then echo "Error: Keyfile $binkeyfile was not removed by ${SWTPM_INTERFACE} tpm." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Saving the volatile state failed." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_getcap000077500000000000000000000041071421141172300164210ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-getcap" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Get the capabilities flags from the TPM act=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -c) if [ $? -ne 0 ]; then echo "Error: Could not get the capability flags of the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after getting capabilities." exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_hashing000077500000000000000000000111271421141172300165770ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-hashing" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit before the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (1): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset the establishment bit via locality 3 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 3 if [ $? -ne -0 ]; then echo "Error: Could not set locality 3" exit 1 fi # \x40 or \x0B seems to confuse 'normal' echo swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0A\x40\x00\x00\x0B') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could not reset the establishment bit" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the reset RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (3): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # back to locality 0 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: Could not set locality 0." exit 1 fi # Read from a file dd if=/dev/zero bs=1024 count=1024 2>/dev/null| \ run_swtpm_ioctl ${SWTPM_INTERFACE} -h - # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 d8 0e 7a 7b 3c 37 88 7d b4 c2 88 08 1d a7 53 f6 4b 11 3a 9c' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_hashing2000077500000000000000000000132121421141172300166560ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-hashing2" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit before the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (1): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset the establishment bit; we switch to locality 0 and reset via locality 3 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: Could not set locality 0" exit 1 fi for ((l = 0; l <= 2; l++)); do # Resetting via locality 2 must fail ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -r $l 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could reset the establishment bit via locality $l" exit 1 fi exp="TPM result from PTM_RESET_TPMESTABLISHED: 0x3d" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi done # We expect the same results for the TPM_ResetEstablishment command for ((l = 0; l <= 2; l++)); do # Set locality run_swtpm_ioctl ${SWTPM_INTERFACE} -l $l if [ $? -ne 0 ]; then echo "Error: Could not choose locality $l" exit 1 fi # Have to use external echo command swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0a\x40\x00\x00\x0b') exp=' 00 c4 00 00 00 0a 00 00 00 3d' if [ "$RES" != "$exp" ]; then echo "Error: Could reset TPM establishment bit in locality $l using command" echo "expected: $exp" echo "received: $RES" exit 1 fi done # Resetting via locality 3 must work run_swtpm_ioctl ${SWTPM_INTERFACE} -l 3 if [ $? -ne 0 ]; then echo "Error: Could not reset the establishment bit via locality 3" exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0a\x40\x00\x00\x0b') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could reset TPM establishment bit in locality 3 using command" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the reset RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (3): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Read from a file dd if=/dev/zero bs=1024 count=1024 2>/dev/null |\ run_swtpm_ioctl ${SWTPM_INTERFACE} -h - # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 d8 0e 7a 7b 3c 37 88 7d b4 c2 88 08 1d a7 53 f6 4b 11 3a 9c' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_init000077500000000000000000000057171421141172300161310ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-init" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate PID_FILE=$TPM_PATH/swtpm.pid SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null if has_seccomp_support "${SWTPM_EXE}"; then SWTPM_TEST_SECCOMP_OPT="--seccomp action=none" fi run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=$TPM_PATH \ --pid file=$PID_FILE display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi if wait_for_file ${PID_FILE} 4; then echo "Error: ${SWTPM_INTERFACE} TPM did not write pidfile." exit 1 fi PIDF="$(cat $PID_FILE)" if [ "$PIDF" != "${SWTPM_PID}" ]; then echo "Error: ${SWTPM_INTERFACE} TPM wrote pid $PIDF, but found ${SWTPM_PID}." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Init the TPM again but make its state file inaccessible; this only # works if the TPM runs as non-root if [ "$(id -u)" != "0" ]; then chmod 000 "${STATE_FILE}" run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -eq 0 ]; then echo "Error: Unexpected initialization success of the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." exit 1 fi chmod 644 "${STATE_FILE}" # Init the TPM again; now with state file accessible again run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi fi check_seccomp_profile "${SWTPM_EXE}" ${SWTPM_PID} 0 if [ $? -ne 0 ]; then exit 1 fi # Shut down run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_locality000077500000000000000000000056441421141172300170050ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-locality" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Set locality 4 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 4 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 4." exit 1 fi # Set illegal locality 5 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 5 if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM accepted locality 5." exit 1 fi # Set locality 0 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 0." exit 1 fi # In locality 2 we can reset PCR 20 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 2 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 2." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset PCR 20 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could not reset PCR 20 in locality 2" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut down TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_migration_key000077500000000000000000000174341421141172300200260ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. # set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-test-migration-key}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" MIGRATION_PASSWORD="migration" VOLATILESTATE=${TESTDIR}/data/migkey1/volatilestate.bin tpmstatedir=$(mktemp -d) if [ -z "$tpmstatedir" ]; then echo "Could not create temporary directory." exit 1 fi migpwdfile=$(mktemp) if [ -z "$migpwdfile" ]; then echo "Could not create temporary file." exit 1 fi echo -n "$MIGRATION_PASSWORD" > $migpwdfile volatilestatefile=$(mktemp) if [ -z "$volatilestatefile" ]; then echo "Could not create temporary file." exit 1 fi SWTPM_CMD_UNIX_PATH=${tpmstatedir}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${tpmstatedir}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $migpwdfile $volatilestatefile $tpmstatedir } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common # make a backup of the volatile state export TPM_PATH=$tpmstatedir cp ${TESTDIR}/data/tpmstate1/* $TPM_PATH run_swtpm ${SWTPM_INTERFACE} \ --migration-key pwdfile=$migpwdfile,remove=false,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Initializing the ${SWTPM_INTERFACE} TPM failed." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Read PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Assert physical presence swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x40\x00\x00\x0A\x00\x20') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TSC_PhysicalPresence(ENABLE)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Create a big NVRAM Area with 4000 bytes (0xfa0) tmp='\x00\xC1\x00\x00\x00\x65\x00\x00\x00\xcc\x00\x18\x00\x00\x00\x01' tmp+='\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x17\x00\x01\x00\x01\x00\x00\x00\x00\x00\x0f' tmp+='\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00' swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} $tmp) exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_NVDefineSpace()" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state into a file run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $volatilestatefile if [ $? -ne 0 ]; then echo "Error: Could not save the volatile state to ${volatilestatefile}." exit 1 fi if [ ! -r $volatilestatefile ]; then echo "Error: Volatile state file $volatilestatefile does not exist." exit 1 fi #ls -l $volatilestatefile size=$(get_filesize $volatilestatefile) expsize=1324 if [ $size -ne $expsize ]; then echo "Error: Unexpected size of volatile state file." echo " Expected file with size of $expsize, found $size bytes." exit 1 fi tmp=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -g | cut -d":" -f2) if [ $? -ne 0 ]; then echo "Error: Could not get the configration flags of the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ "$tmp" != " 0x2" ]; then echo "Error: Unexpected configuration flags: $tmp; expected 0x2." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s echo "Test 1: Ok" # Start the vTPM again and load the encrypted volatile state into it run_swtpm ${SWTPM_INTERFACE} \ --migration-key pwdfile=$migpwdfile,remove=false,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Do NOT init the TPM now; first load volatile state # load the encrypted volatile state into it run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $volatilestatefile if [ $? -ne 0 ]; then echo "Error: Could not load encrypted volatile state into TPM." exit 1 fi # Now init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Initializing the ${SWTPM_INTERFACE} TPM failed." exit 1 fi # Read PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 2: Ok" # Start the vTPM again and load the encrypted volatile state into it # This time we make this fail since we don't provide the migration key run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Do NOT init the TPM now; first load volatile state # load the encrypted volatile state into it # This will not work; the TPM writes the data into the volatile state file # and validates it ERR=$(run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $volatilestatefile 2>&1) if [ $? -eq 0 ]; then echo "Error: Could load encrypted volatile state into TPM." exit 1 fi exp="TPM result from PTM_SET_STATEBLOB: 0xd" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 3: Ok" # In this test we now feed it an encrypted volatile state # Start the vTPM again and load the encrypted volatile state into it run_swtpm ${SWTPM_INTERFACE} \ --migration-key pwdfile=$migpwdfile,remove=true,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # load the encrypted volatile state into it run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $VOLATILESTATE if [ $? -ne 0 ]; then echo "Error: Could not load encrypted volatile state into TPM." exit 1 fi # Now init the TPM; this must work run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Read PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 4: Ok" swtpm-0.6.3/tests/_test_migration_key_2000077500000000000000000000005771421141172300202470ustar00rootroot00000000000000#!/bin/bash # Run the test_save_load_encrypted_state with swtpm_ioctl using the # read/write interface rather than ioctl export VTPM_NAME="vtpm-test2-migration-key" cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 bash test_migration_key ret=$? [ $ret -ne 0 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 bash test_migration_key ret=$? [ $ret -ne 0 ] && exit $ret exit 0 swtpm-0.6.3/tests/_test_print_capabilities000077500000000000000000000041341421141172300210230ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} PATH=$ROOT/src/swtpm:$PATH [ "${SWTPM_IFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common msg="$(${SWTPM_EXE} ${SWTPM_IFACE} --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities" echo "${msg}" exit 1 fi if has_seccomp_support "${SWTPM_EXE}"; then seccomp='"cmdarg-seccomp", ' fi if [ "${SWTPM_IFACE}" != "cuse" ]; then noncuse='"tpm-send-command-header", "flags-opt-startup", ' fi exp='{ "type": "swtpm", "features": [ '${noncuse}${seccomp}'"cmdarg-key-fd", "cmdarg-pwd-fd" ] }' if [ "${msg}" != "${exp}" ]; then echo "Unexpected response from ${SWTPM_IFACE} TPM to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 1: OK" msg="$(${SWTPM_SETUP} --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities" echo "${msg}" exit 1 fi # The are some variable parameters at the end, use regex exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 2: OK" # SWTPM_CERT may be run by valgrind if [ -x "$(type -P $(echo "${SWTPM_CERT}" | cut -d" " -f1) )" ]; then msg="$(${SWTPM_CERT} --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities to ${SWTPM_CERT}" echo "${msg}" exit 1 fi exp='{ "type": "swtpm_cert", "features": [ "cmdarg-signkey-pwd", "cmdarg-parentkey-pwd" ] }' if [ "${msg}" != "${exp}" ]; then echo "Unexpected response from ${SWTPM_CERT} to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 3: OK" else echo "Test 2: SKIP -- ${SWTPM_CERT} not found or not an executable" fi exit 0 swtpm-0.6.3/tests/_test_resume_volatile000077500000000000000000000122521421141172300203550ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-resume-volatile" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" tpmstatedir="$(mktemp -d)" if [ -z "$tpmstatedir" ]; then echo "Could not create temporary directory" exit 1 fi SWTPM_CMD_UNIX_PATH=${tpmstatedir}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${tpmstatedir}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $tpmstatedir } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common export TPM_PATH=$tpmstatedir # copy all the state files cp ${TESTDIR}/data/tpmstate1/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Read PCR 10 (extend -ix 10 -ic test) swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s echo "Test 1: Ok" # 2nd test: with encrypted state # copy all the state files cp ${TESTDIR}/data/tpmstate2/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} \ --key pwdfile=${TESTDIR}/data/tpmstate2/pwdfile.txt,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Read PCR 10 (extend -ix 10 -ic test) swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 2: Ok" # 3rd test: with encrypted state using aes-256-cbc # copy all the state files cp ${TESTDIR}/data/tpmstate2b/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} \ --key pwdfile=${TESTDIR}/data/tpmstate2b/pwdfile.txt,mode=aes-256-cbc display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Read PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a') exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 3: Ok" swtpm-0.6.3/tests/_test_save_load_encrypted_state000077500000000000000000000273601421141172300223760ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-test-save-load-encrypted-state}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate KEY=1234567890abcdef1234567890abcdef MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} keyfile=$(mktemp) logfile=$(mktemp) echo "$KEY" > $keyfile function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -f $keyfile $logfile rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null exec 101<$keyfile run_swtpm ${SWTPM_INTERFACE} \ --key fd=101,mode=aes-cbc,format=hex \ --log file=$logfile exec 101>&- display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Could not hash the data." echo "TPM Logfile:" cat $logfile exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Assert physical presence swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x40\x00\x00\x0A\x00\x20') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TSC_PhysicalPresence(ENABLE)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Create a big NVRAM Area with 4000 bytes (0xfa0) tmp='\x00\xC1\x00\x00\x00\x65\x00\x00\x00\xcc\x00\x18\x00\x00\x00\x01' tmp+='\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x17\x00\x01\x00\x01\x00\x00\x00\x00\x00\x0f' tmp+='\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00' swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} $tmp) exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_NVDefineSpace()" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_PERMANENT_STATE_FILE ]; then echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write volatile state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # we will use our own volatile state rm -f $VOLATILE_STATE_FILE $STATE_FILE # Stop the TPM; this will not shut it down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error (2): Could not stop the ${SWTPM_INTERFACE} TPM" echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # load state into the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load permanent state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load volatile state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "TPM Init failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM write the volatile state to a file." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Test 1: Ok" # This time start we start the TPM with a wrong state encryption key # (key used as password) and try to start it. It has to fail and # the state must not have been modified. # volatile state file does not exist sha1_volatile=$(get_sha1_file "${VOLATILE_STATE_FILE}") sha1_permanent=$(get_sha1_file "${STATE_FILE}") echo "sha1(volatile) : $sha1_volatile" echo "sha1(permanent): $sha1_permanent" exec 101<$keyfile run_swtpm ${SWTPM_INTERFACE} \ --key pwdfd=101 \ --log file=$logfile exec 101>&- display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -i 2>&1)" if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization should have failed." echo "TPM Logfile:" cat $logfile exit 1 fi exp="TPM result from PTM_INIT: 0x21" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "${sha1_volatile}" != "$(get_sha1_file "${VOLATILE_STATE_FILE}")" ]; then echo "Error: Volatile state file was modified during failed init." exit 1 fi if [ "${sha1_permanent}" != "$(get_sha1_file "${STATE_FILE}")" ]; then echo "Error: Permanent state file was modified during failed init." exit 1 fi # shut it down run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Test 2: Ok" # This time start we start the TPM with a different cipher and try to # start it. It has to fail and the state must not have been modified. # volatile state file does not exist sha1_volatile=$(get_sha1_file "${VOLATILE_STATE_FILE}") sha1_permanent=$(get_sha1_file "${STATE_FILE}") echo "sha1(volatile) : $sha1_volatile" echo "sha1(permanent): $sha1_permanent" # we need a 256bit key echo "${KEY}${KEY}" > $keyfile run_swtpm ${SWTPM_INTERFACE} \ --key pwdfile=$keyfile,mode=aes-256-cbc \ --log file=$logfile display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -i 2>&1)" if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization should have failed." echo "TPM Logfile:" cat $logfile exit 1 fi exp="TPM result from PTM_INIT: 0x28" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "${sha1_volatile}" != "$(get_sha1_file "${VOLATILE_STATE_FILE}")" ]; then echo "Error: Volatile state file was modified during failed init." exit 1 fi if [ "${sha1_permanent}" != "$(get_sha1_file "${STATE_FILE}")" ]; then echo "Error: Permanent state file was modified during failed init." exit 1 fi echo "Test 3: Ok" # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_save_load_state000077500000000000000000000175061421141172300203220ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-test-save-load-state}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} logfile=$(mktemp) function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -f $logfile rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --log file=$logfile display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." echo "TPM Logfile:" cat $logfile exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Assert physical presence swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x40\x00\x00\x0A\x00\x20') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TSC_PhysicalPresence(ENABLE)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Create a big NVRAM Area with 4000 bytes (0xfa0) tmp='\x00\xC1\x00\x00\x00\x65\x00\x00\x00\xcc\x00\x18\x00\x00\x00\x01' tmp+='\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01' tmp+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00\x17\x00\x01\x00\x01\x00\x00\x00\x00\x00\x0f' tmp+='\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' tmp+='\x00\x00\x00\x00\x00' swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} $tmp) exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_NVDefineSpace()" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_PERMANENT_STATE_FILE ]; then echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write volatile state file $MY_VOLATILE_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # we will use our own volatile state rm -f $VOLATILE_STATE_FILE $STATE_FILE # Stop the TPM; this will not shut it down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # load state into the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load permanent state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load volatile state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "TPM Init failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_setbuffersize000077500000000000000000000052361421141172300200420ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. # set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-setbuffersize" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} OUTFILE=${TPM_PATH}/output function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Check the buffer size run_swtpm_ioctl ${SWTPM_INTERFACE} -b 0 > ${OUTFILE} if [ $? -ne 0 ]; then echo "Error: Could not get the buffersize of the ${SWTPM_INTERFACE} TPM." exit 1 fi cat ${OUTFILE} if [ -z "$(grep "TPM buffersize" ${OUTFILE} | grep 4096)" ]; then echo "Error: The TPM buffersize of the ${SWTPM_INTERFACE} TPM is not 4096." exit 1 fi # set the buffer size run_swtpm_ioctl ${SWTPM_INTERFACE} -b 4000 > ${OUTFILE} if [ $? -ne 0 ]; then echo "Error: Could not set the buffersize of the ${SWTPM_INTERFACE} TPM." exit 1 fi cat ${OUTFILE} if [ -z "$(grep "TPM buffersize" ${OUTFILE} | grep 4000)" ]; then echo "Error: The TPM buffersize of the ${SWTPM_INTERFACE} TPM is not 4000." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Set the buffer size -- should fail ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -b 4096 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could set the buffersize while the ${SWTPM_INTERFACE} TPM is running." exit 1 fi exp="TPM result from PTM_SET_BUFFERSIZE: 0xa" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_swtpm_bios000077500000000000000000000075441421141172300173540ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM_BIOS=$ROOT/src/swtpm_bios/swtpm_bios VTPM_NAME="vtpm-test-swtpm-bios" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate PID_FILE=$TPM_PATH/swtpm.pid SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpmstate dir=$TPM_PATH --pid file=$PID_FILE display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi if wait_for_file ${PID_FILE} 4; then echo "Error: ${SWTPM_INTERFACE} TPM did not write pidfile." exit 1 fi PIDF="$(cat $PID_FILE)" if [ "$PIDF" != "${SWTPM_PID}" ]; then echo "Error: ${SWTPM_INTERFACE} TPM wrote pid $PIDF, but found ${SWTPM_PID}." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} -o 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} -n --cs 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not self-test the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} -n -u 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi # will NOT work -- we get error output in $res res=$(run_swtpm_bios ${SWTPM_INTERFACE} -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ $ret -ne 128 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret." exit 1 fi # will NOT work (wrong device) -- we get error output in $res res=$(TPM_DEVICE=/dev/${VTPM_NAME}123 ${SWTPM_BIOS} -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on wrong device." exit 1 fi if [ $ret -ne 255 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 255, had $ret." exit 1 fi # RESET TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} --cs -u 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM." exit 1 fi # will NOT work -- we get error output in $res res=$(run_swtpm_bios ${SWTPM_INTERFACE} -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ $ret -ne 128 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_derived_keys000077500000000000000000000433131421141172300205770ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-derived-keys" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} tpmstatedir="$(mktemp -d)" if [ -z "$tpmstatedir" ]; then echo "Could not create temporary directory" exit 1 fi SWTPM_CMD_UNIX_PATH=${tpmstatedir}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${tpmstatedir}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $tpmstatedir } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common export TPM_PATH=$tpmstatedir # copy all the state files cp ${TESTDIR}/data/tpm2state1/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} --tpm2 kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Create a key # @param1: reset (!= 0) TPM before creating key; # @param2: whether to send TPM2_Startup # @param3: command to send # @param4: expected return value # @param5: allowed failure return value to skip test function tx_cmd() { local reset="$1" local startup="$2" local cmd="$3" local exp="$4" local allowed_error="$5" local RES tmp if [ "$reset" != "0" ]; then run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not send TPM_INIT" return 1 fi fi if [ "$startup" != "0" ]; then swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') tmp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$tmp" ]; then echo "Error: Did not get expected response from TPM2_Startup" echo "expected: $tmp" echo "received: $RES" return 1 fi exec 100>&- fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${cmd}) if [ "$RES" == "$allowed_error" ]; then echo "Skip: Encountered allowed error response ($allowed_error)" elif [ "$RES" != "$exp" ]; then echo "Error: Did not get expected return from creating key" echo "expected: $exp" echo "received: $RES" return 1 fi exec 100>&- return 0 } # Older versions of libtpms do not support TDES # So we may skip the test in case we hit this error error_unsupt_algo=' 80 01 00 00 00 0a 00 00 02 d6' # Create a primary RSA key and expect a predictable return value # tsscreateprimary -hi e -v # -> creates key with handle 0x80 00 00 00 test1_cmd='\x80\x02\x00\x00\x00\x43\x00\x00\x01\x31\x40\x00\x00\x0b\x00\x00' test1_cmd+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test1_cmd+='\x00\x00\x1a\x00\x01\x00\x0b\x00\x03\x04\x72\x00\x00\x00\x06\x00' test1_cmd+='\x80\x00\x43\x00\x10\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' test1_cmd+='\x00\x00\x00' test1_exp=' 80 02 00 00 01 fa 00 00 00 00 80 00 00 00 00 00' test1_exp+=' 01 e3 01 1a 00 01 00 0b 00 03 04 72 00 00 00 06 00' test1_exp+=' 80 00 43 00 10 08 00 00 00 00 00 01 00 b5 0a c8 18' test1_exp+=' 00 01 82 b6 53 63 fc a1 ba 4d 13 d2 1e 05 63 08 bb' test1_exp+=' df b3 95 c5 e0 d7 42 f8 c4 21 f1 c7 df ac ee 57 e4' test1_exp+=' 3d 80 7b da 33 95 76 56 cc 73 df 0b 33 db 4b 3a f0' test1_exp+=' d1 80 86 a2 35 df a9 a7 82 4b 6d 1e 88 d7 e8 d9 73' test1_exp+=' 0b 6c d3 c5 ef b9 5c fb 92 69 d8 c0 d8 e9 a1 fa a3' test1_exp+=' 72 dc 6a 3e 8c c4 a7 8e 9f b8 f2 0e b3 64 e0 8c cb' test1_exp+=' f0 02 31 d1 b6 ee 2c de e7 c7 92 7e 34 b8 46 80 7e' test1_exp+=' f6 0a f9 b6 57 e0 91 51 18 27 5b fe 8a e7 22 d2 41' test1_exp+=' e1 e6 16 d6 04 e0 03 a9 1c be 5d 6b 37 a7 d7 03 45' test1_exp+=' 7e dc 96 ad 5d ea bb 99 c5 e1 07 a9 70 6f b2 89 d9' test1_exp+=' 4b c1 cc 01 fa df 6d 74 de ca f9 41 bf be 89 bd 53' test1_exp+=' 79 ee 28 8e ef 81 16 c2 d1 6d cf 10 49 06 23 ba b3' test1_exp+=' ab d7 27 fc 7c f2 6a f4 8a 75 5b de ea dc e9 33 0a' test1_exp+=' e8 d5 70 2b 5a 94 03 f7 5e 75 5d 76 08 3b 6e c1 2c' test1_exp+=' 1f cb 28 68 ab 82 87 49 70 96 96 56 ac d7 00 37 00' test1_exp+=' 00 00 00 00 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8' test1_exp+=' 99 6f b9 24 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78' test1_exp+=' 52 b8 55 01 00 10 00 04 40 00 00 0b 00 04 40 00 00' test1_exp+=' 0b 00 00 00 20 28 d0 26 fa fd 74 91 06 74 3e 27 c4' test1_exp+=' 28 05 51 58 5e 5d 17 66 8e b5 21 83 5e d6 01 27 ef' test1_exp+=' fc 05 d4 80 21 40 00 00 0b 00 40 dc 19 bf 88 fc 7b' test1_exp+=' d8 5c 0b 40 fb 0f ec b0 af 6b f1 46 3e 26 bf bf 74' test1_exp+=' 95 ec 0e 6f 60 b3 e7 dd 29 55 11 3f 9f ee 9f 75 27' test1_exp+=' d8 b5 4a 51 72 6e dc a1 68 a6 0a 6d d3 70 1f 0c 00' test1_exp+=' df 79 60 23 86 83 e0 00 22 00 0b 45 fe 98 72 0a c6' test1_exp+=' cf 0a ca 16 37 28 d9 e2 33 a9 d5 4f 5d b5 d3 78 bf' test1_exp+=' 40 20 60 b3 85 8d 41 ff c7 00 00 01 00 00' # Create a primary ECC key and expect a predictable return value # tsscreateprimary -hi e -ecc bnp256 -v # -> creates key with handle 0x80 00 00 00 test2_cmd='\x80\x02\x00\x00\x00\x43\x00\x00\x01\x31\x40\x00\x00\x0b\x00\x00' test2_cmd+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test2_cmd+='\x00\x00\x1a\x00\x23\x00\x0b\x00\x03\x04\x72\x00\x00\x00\x06\x00' test2_cmd+='\x80\x00\x43\x00\x10\x00\x03\x00\x10\x00\x00\x00\x00\x00\x00\x00' test2_cmd+='\x00\x00\x00' test2_exp=' 80 02 00 00 01 3a 00 00 00 00 80 00 00 00 00 00 01 23' test2_exp+=' 00 5a 00 23 00 0b 00 03 04 72 00 00 00 06 00 80 00 43' test2_exp+=' 00 10 00 03 00 10 00 20 15 86 c2 64 96 e4 b1 07 83 17 de 90' test2_exp+=' da 9e df 61 42 e2 12 6b 94 48 c9 d9 bc e6 31 03 8e 8b fb 1f' test2_exp+=' 00 20 37 26 ca 32 f2 6d 75 cb 1f 5d e8 8e b6 3e 96 8e 10 a0' test2_exp+=' 1c df 55 91 4a 9b 50 a1 2a e6 a1 ee 32 45 00 37 00 00 00 00' test2_exp+=' 00 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae' test2_exp+=' 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00 10 00 04 40' test2_exp+=' 00 00 0b 00 04 40 00 00 0b 00 00 00 20 28 d0 26 fa fd 74 91' test2_exp+=' 06 74 3e 27 c4 28 05 51 58 5e 5d 17 66 8e b5 21 83 5e d6 01' test2_exp+=' 27 ef fc 05 d4 80 21 40 00 00 0b 00 40 99 3f 24 8d 87 28 fe' test2_exp+=' bb 5d 1b be fc 12 2c cd 4e 5b 03 22 7a 78 00 3b 64 76 ec 08' test2_exp+=' 11 2f 4c 36 7b 36 f7 83 1a 59 74 19 fe 52 45 81 f7 08 bc be' test2_exp+=' b0 e1 99 37 1a 3e 7b ba cb dc 3e 20 d8 51 82 45 24 00 22 00' test2_exp+=' 0b ac 4c a0 86 53 fa 68 b2 c9 54 f5 7e f7 c2 54 12 0a 08 03' test2_exp+=' de 8e 96 e1 f1 89 97 52 a8 1a fb 0b cc 00 00 01 00 00' # Create an AES key and expect a predictable return value # tsscreateloaded -hp 40000001 -rsa -des -v # -> creates key with handle 0x80 00 00 00 test3_cmd='\x80\x02\x00\x00\x00\x35\x00\x00\x01\x91\x40\x00\x00\x01\x00\x00' test3_cmd+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test3_cmd+='\x00\x00\x12\x00\x25\x00\x0b\x00\x06\x04\x60\x00\x00\x00\x06\x00' test3_cmd+='\x80\x00\x43\x00\x00' test3_exp=' 80 02 00 00 00 71 00 00 00 00 80 00 00 00 00 00 00' test3_exp+=' 5a 00 00 00 32 00 25 00 0b 00 06 04 60 00 00 00 06 00 80' test3_exp+=' 00 43 00 20 b4 1c 16 e3 78 1e dc 6c 8a 84 ce 27 f1 f3 8c' test3_exp+=' 8c 67 fe ea 6e 1f 14 2d db 26 2e 16 dd 5c fb f0 fb 00 22' test3_exp+=' 00 0b d4 2a 69 2b 4c b7 31 e2 65 d4 14 61 10 aa 16 ec b2' test3_exp+=' 7f a3 27 15 1b 5c 7c 22 98 90 1f cd f2 9e bc 00 00 01 00' test3_exp+=' 00' # Create a TDES (0x03) key and expect a predictable return value # (tsscreateloaded does not support TDES) # -> creates key with handle 0x80 00 00 00 test4_cmd='\x80\x02\x00\x00\x00\x35\x00\x00\x01\x91\x40\x00\x00\x01\x00\x00' test4_cmd+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test4_cmd+='\x00\x00\x12\x00\x25\x00\x0b\x00\x06\x04\x60\x00\x00\x00\x03\x00' test4_cmd+='\x80\x00\x43\x00\x00' #^^^^ <- TDES test4_exp=' 80 02 00 00 00 71 00 00 00 00 80 00 00 00 00 00 00' test4_exp+=' 5a 00 00 00 32 00 25 00 0b 00 06 04 60 00 00 00 03' test4_exp+=' 00 80 00 43 00 20 91 28 1c bc ac 9d d6 6d 29 33 82' test4_exp+=' 74 05 16 d4 ab 4c 6a 6c 95 cf 60 8e a8 69 43 1f e2' test4_exp+=' 37 13 67 eb 00 22 00 0b 9e 45 d0 46 1f 72 a7 eb 24' test4_exp+=' 67 cf 02 67 5a e1 ee bb ab 29 13 44 ba d1 e1 14 fd' test4_exp+=' 1f 73 33 db 5f 33 00 00 01 00 00' # Create a primary RSA key and expect a predictable return value # tsscreateprimary -hi e -dp -v # -> creates key with handle 0x80 00 00 00 test5_cmd1='\x80\x02\x00\x00\x00\x3b\x00\x00\x01\x31\x40\x00\x00\x0b\x00\x00' test5_cmd1+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test5_cmd1+='\x00\x00\x12\x00\x08\x00\x0b\x00\x03\x04\x72\x00\x00\x00\x0a\x00' test5_cmd1+='\x0b\x00\x22\x00\x00\x00\x00\x00\x00\x00\x00' test5_exp1=' 80 02 00 00 01 12 00 00 00 00 80 00 00 00 00 00' test5_exp1+=' 00 fb 00 32 00 08 00 0b 00 03 04 72 00 00 00 0a' test5_exp1+=' 00 0b 00 22 00 20 5f bc a0 5c 6c b0 60 fe 76 c5' test5_exp1+=' 0f f2 0e eb e8 52 9f 2b e7 3b 06 6a b4 3f 88 6f' test5_exp1+=' 51 1f cd d8 c1 1f 00 37 00 00 00 00 00 20 e3 b0' test5_exp1+=' c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae' test5_exp1+=' 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00' test5_exp1+=' 10 00 04 40 00 00 0b 00 04 40 00 00 0b 00 00 00' test5_exp1+=' 20 28 d0 26 fa fd 74 91 06 74 3e 27 c4 28 05 51' test5_exp1+=' 58 5e 5d 17 66 8e b5 21 83 5e d6 01 27 ef fc 05' test5_exp1+=' d4 80 21 40 00 00 0b 00 40 8e 6b 7d 82 b0 d4 6b' test5_exp1+=' 04 f3 9d a7 54 5d f3 5e 70 79 c3 7a 8c 5b 7a 08' test5_exp1+=' cb 03 62 24 47 1a e3 7d de 49 95 23 2b d7 69 6b' test5_exp1+=' 23 6b 2f b5 ed 35 ee 9d c4 01 3f 3b 37 db 2f ba' test5_exp1+=' a4 8f 80 68 f9 c1 d2 ff 70 00 22 00 0b 6a 1a f5' test5_exp1+=' 61 1c 58 6a 02 3f 3f 12 15 86 67 57 7e da fb 30' test5_exp1+=' 0a 6b 66 b4 68 99 77 46 f8 4c ea ef 8b 00 00 01' test5_exp1+=' 00 00' # Create a derived key with this primary key as parent: # createloaded -hp 80000000 -der -ecc bnp256 -den -kt f -kt p -v # -> creates key with handle 0x80 00 00 01 test5_cmd2='\x80\x02\x00\x00\x00\x39\x00\x00\x01\x91\x80\x00\x00\x00\x00\x00' test5_cmd2+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00' test5_cmd2+='\x00\x00\x16\x00\x23\x00\x0b\x00\x02\x04\x52\x00\x00\x00\x10\x00' test5_cmd2+='\x10\x00\x10\x00\x10\x00\x00\x00\x00' test5_exp2+=' 80 02 00 00 00 95 00 00 00 00 80 00 00 01 00 00' test5_exp2+=' 00 7e 00 00 00 56 00 23 00 0b 00 02 04 52 00 00' test5_exp2+=' 00 10 00 10 00 10 00 10 00 20 af 79 72 26 52 4e' test5_exp2+=' 14 e7 99 c2 a4 49 60 2a 19 8e 78 0c 30 c5 6f 65' test5_exp2+=' f1 e6 26 3a 67 ee 5a df 3c 31 00 20 cd b5 62 59' test5_exp2+=' 83 2e ad 91 1c 81 83 3e 92 22 8e 9d d0 71 bf 65' test5_exp2+=' 5c bc 38 24 6a a7 07 e6 0d eb 9d d3 00 22 00 0b' test5_exp2+=' be 61 98 28 b4 ea 33 db b0 24 39 2d 9f b4 0b 71' test5_exp2+=' ab ff ed 4b 55 02 f0 4e 3e 66 41 91 73 96 25 b6' test5_exp2+=' 00 00 01 00 00' # # The issue is that 32bit TPMs produce different results than # 64bit TPMs. We only test 64bit TPMs with the above expected # return values. We also only test little endian # case "$(uname -s)" in Linux) # Only 64bit apps will link with libs in /lib64/ dirs if [ -n "$(grep -E "\/lib64\/" /proc/${SWTPM_PID}/maps)" ] && \ [ -n "$(lscpu | grep "Little Endian")" ]; then tx_cmd 1 0 "$test1_cmd" "$test1_exp" "" || exit 1 && echo "Test 1: OK" tx_cmd 1 1 "$test2_cmd" "$test2_exp" "" || exit 1 && echo "Test 2: OK" tx_cmd 1 1 "$test3_cmd" "$test3_exp" "" || exit 1 && echo "Test 3: OK" tx_cmd 1 1 "$test4_cmd" "$test4_exp" "$error_unsupt_algo" || exit 1 && echo "Test 4: OK" tx_cmd 1 1 "$test5_cmd1" "$test5_exp1" "" || exit 1 tx_cmd 0 0 "$test5_cmd2" "$test5_exp2" "" || exit 1 && echo "Test 5: OK" else echo "This test currently only runs with 64bit little endian swtpm. ${SWTPM_EXE} seems 32bit or big endian." fi ;; *) echo "This test currently only runs on Linux" ;; esac # Get revision of TPM 2.0 implementation; we need >= 155 for subsequent tests revision=$(run_swtpm_ioctl ${SWTPM_INTERFACE} --info 1 | sed 's/.*,"revision":\([^\}]*\).*/\1/') run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ $revision -lt 155 ]; then echo "Skipping next tests since libtpms implements TPM 2.0 revision $revision, but need >= 155" exit 0 fi # Repeat the tests for the 'fixed' CryptAdjustPrimeCandidate test, which works # on 32 bit and 64 bit machines and produces the same results echo "Testing new CryptAdjustPrimeCandidate implementation" # copy all the state files; the files need libtpms (0.8.0) with # TPM 2.0 revsion 155; there the seeds are setup so that the fixed # RSA key generation algorithm is used cp -f ${TESTDIR}/data/tpm2state4/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} --tpm2 kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi test1_exp=' 80 02 00 00 01 fa 00 00 00 00 80 00 00 00 00 00 01 e3 01 1a 00 01 00 0b 00 03 04 72 00 00 00 06 00 80 00 43 00 10 08 00 00 00 00 00 01 00 9b ef 34 ef e5 b1 2a 2b bc 85 71 5c 59 a5 67 f2 fe 13 38 15 c0 45 68 05 b1 27 c3 ef 63 89 21 c0 13 39 47 6d 99 82 b1 7c 79 d9 b7 9f 50 1c 2c 05 22 c3 53 02 76 f1 9b 8c 61 31 0d af a5 c1 12 28 f6 2b 02 24 d8 b5 04 51 c8 74 38 95 00 a9 24 88 40 a8 7f ce 49 eb f9 bd 67 f1 96 a8 39 3e e6 af 8c 7d ae 29 48 dc e3 64 1a 54 58 70 30 9f ae 96 de f4 2e 79 b1 89 fd 81 8f 29 b7 01 ab 92 30 32 0f 2c e9 0c 4f 6b cd aa b1 2e d1 dc 91 b0 d0 13 50 07 89 52 57 ce af e2 cf 4a 01 c2 7d 04 35 01 0e 7b 3e 42 98 91 71 a6 65 ab f2 31 97 4f 70 9c f8 fe a9 d1 5b 1c be 8c fc b8 0f 84 cc a1 52 42 94 74 92 76 94 0b 8f b4 95 8c b8 1e d5 7d 58 d1 3a 7f 8b 22 50 fc 57 39 6e bb e5 29 c8 7c b1 6b dd 11 9d 3b 06 2c 63 e4 d5 55 56 93 8c e7 06 86 2b 15 91 33 7c b2 14 43 57 5b 94 11 77 f4 6c d9 00 37 00 00 00 00 00 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00 10 00 04 40 00 00 0b 00 04 40 00 00 0b 00 00 00 20 28 d0 26 fa fd 74 91 06 74 3e 27 c4 28 05 51 58 5e 5d 17 66 8e b5 21 83 5e d6 01 27 ef fc 05 d4 80 21 40 00 00 0b 00 40 e7 23 e1 bb 81 90 bb 1f 1a 32 d7 bd 07 f5 40 ad 27 a8 cd 70 1a 17 d6 af b6 8f 86 6d 6f c1 5d 65 de 07 82 63 2a da ac 20 73 90 a0 f4 5f cd c8 61 84 79 5b 9d c0 19 98 62 94 fb 35 f0 5d 91 f5 21 00 22 00 0b 07 eb bd 34 07 3e 1e 20 d6 cb b6 ea 62 61 1a 12 4e 84 85 b5 bf 5e 1b bd f4 6b 93 6a 1d 5f 32 3b 00 00 01 00 00' test2_exp=' 80 02 00 00 01 3a 00 00 00 00 80 00 00 00 00 00 01 23 00 5a 00 23 00 0b 00 03 04 72 00 00 00 06 00 80 00 43 00 10 00 03 00 10 00 20 ff cc 72 69 28 1a fd 2a 2c 5d 12 8d 7a 9e 7c 3e 6f 86 8a d7 e5 93 a0 f0 de 01 30 50 94 51 31 8f 00 20 6b 15 ca 0d 9a 67 4a e9 b6 d0 23 d2 e5 98 71 be 83 b5 f7 66 3f 63 ca 95 e7 7a e7 44 c4 94 89 95 00 37 00 00 00 00 00 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00 10 00 04 40 00 00 0b 00 04 40 00 00 0b 00 00 00 20 28 d0 26 fa fd 74 91 06 74 3e 27 c4 28 05 51 58 5e 5d 17 66 8e b5 21 83 5e d6 01 27 ef fc 05 d4 80 21 40 00 00 0b 00 40 fa bb 14 5e 67 43 43 64 c8 29 e9 9a 7c 81 5e ff 4a 29 bb 5e 72 75 03 5f 62 d2 6d 7a 90 0a 6e 6d 68 ef 83 9d df 77 1f 76 0f c8 0d 1d 86 be 62 09 0b 56 68 2a f3 92 11 b1 2d 35 03 82 d1 ea d9 8a 00 22 00 0b 5f 43 81 4d 6a ed b8 36 cf 2d 92 50 44 a4 8f 03 8a ad 08 32 f5 23 49 6f 85 76 8b 95 a4 37 18 8e 00 00 01 00 00' test3_exp=' 80 02 00 00 00 71 00 00 00 00 80 00 00 00 00 00 00 5a 00 00 00 32 00 25 00 0b 00 06 04 60 00 00 00 06 00 80 00 43 00 20 25 f3 2c cf 3d 14 ed 18 a9 ae 67 82 28 7b 3b 21 7c d1 f4 24 12 d1 74 d5 69 7d 73 1b 6d ae 45 04 00 22 00 0b c5 fa ae 5e 37 7a ad d0 78 4e 1b e5 63 9c 5b a8 17 03 82 cb a0 e8 ab 39 40 69 24 48 df 72 8b c8 00 00 01 00 00' test4_exp=' 80 02 00 00 00 71 00 00 00 00 80 00 00 00 00 00 00 5a 00 00 00 32 00 25 00 0b 00 06 04 60 00 00 00 03 00 80 00 43 00 20 58 3a 75 c7 29 b6 df 2f 3c a1 1d 2a f3 79 ff aa 62 72 94 ec 4f c2 ad fa 5a 66 39 c3 4a 18 ad ae 00 22 00 0b 63 31 31 24 c4 61 f0 10 a4 46 53 85 c8 bd b3 d9 66 e4 4b a8 b9 bd 68 ad be 58 3e 10 09 20 66 dc 00 00 01 00 00' test5_exp1=' 80 02 00 00 01 12 00 00 00 00 80 00 00 00 00 00 00 fb 00 32 00 08 00 0b 00 03 04 72 00 00 00 0a 00 0b 00 22 00 20 60 5c 90 40 d5 ef 80 59 70 f4 90 3e 43 7a ce 49 1e 06 06 f0 e9 79 39 e4 a0 a1 8b d5 12 ca 86 9a 00 37 00 00 00 00 00 20 e3 b0 c4 42 98 fc 1c 14 9a fb f4 c8 99 6f b9 24 27 ae 41 e4 64 9b 93 4c a4 95 99 1b 78 52 b8 55 01 00 10 00 04 40 00 00 0b 00 04 40 00 00 0b 00 00 00 20 28 d0 26 fa fd 74 91 06 74 3e 27 c4 28 05 51 58 5e 5d 17 66 8e b5 21 83 5e d6 01 27 ef fc 05 d4 80 21 40 00 00 0b 00 40 5a 84 8d d0 73 da 49 f6 76 84 6e d1 56 13 39 4d 4b 67 0a 68 97 71 c9 a4 92 a6 aa 6d 30 4b 19 6c 69 fc a7 d5 b9 5c 8f 5a af 0c f6 72 b9 85 c5 d4 0a 09 f8 f7 16 4d 11 bc 5d ec cc 48 02 15 ce 79 00 22 00 0b 04 13 09 39 42 b3 86 80 67 68 2a d7 27 e3 c7 44 1d 1c b6 65 23 c3 ee f0 b8 b8 b5 ff ee 49 1d 4b 00 00 01 00 00' test5_exp2=' 80 02 00 00 00 95 00 00 00 00 80 00 00 01 00 00 00 7e 00 00 00 56 00 23 00 0b 00 02 04 52 00 00 00 10 00 10 00 10 00 10 00 20 af 9f be fc c8 95 21 71 04 2d 7d db 3f 42 aa 54 cc 2f a0 cf 55 82 78 f4 3f 01 88 27 46 53 2c 88 00 20 dc ad 67 2f d1 ea 89 01 f5 27 1f 58 3f a5 da 52 85 50 98 d5 06 81 10 13 86 12 d7 23 55 12 ea 0c 00 22 00 0b 72 c2 60 3f c8 bb 79 ea 92 86 7e a3 df 57 8d 15 e3 f1 10 a2 f9 1c a6 80 41 c3 cf e1 fa 43 83 2f 00 00 01 00 00' tx_cmd 1 0 "$test1_cmd" "$test1_exp" "" || exit 1 && echo "Test 1: OK" tx_cmd 1 1 "$test2_cmd" "$test2_exp" "" || exit 1 && echo "Test 2: OK" tx_cmd 1 1 "$test3_cmd" "$test3_exp" "" || exit 1 && echo "Test 3: OK" tx_cmd 1 1 "$test4_cmd" "$test4_exp" "" || exit 1 && echo "Test 4: OK" tx_cmd 1 1 "$test5_cmd1" "$test5_exp1" "" || exit 1 tx_cmd 0 0 "$test5_cmd2" "$test5_exp2" "" || exit 1 && echo "Test 5: OK" run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi exit 0 swtpm-0.6.3/tests/_test_tpm2_encrypted_state000077500000000000000000000155701421141172300213230ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME=${VTPM_NAME:-vtpm-test-tpm2-encrypted-state} SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate KEY=1234567890abcdef1234567890abcdef BINKEY='\x12\x34\x56\x78\x90\xab\xcd\xef\x12\x34\x56\x78\x90\xab\xcd\xef' SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock keyfile=${TPM_PATH}/keyfile logfile=${TPM_PATH}/logfile binkeyfile=${TPM_PATH}/binkeyfile echo "$KEY" > ${keyfile} echo -en "$BINKEY" > ${binkeyfile} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --key file=$keyfile,mode=aes-cbc,format=hex,remove \ --log file=$logfile \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_file_gone ${keyfile} 4; then echo "Error: Keyfile $keyfile was not removed by ${SWTPM_INTERFACE} tpm." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." echo "TPM Logfile:" cat $logfile exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Saving the volatile state failed." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi tmp=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -g | cut -d":" -f2) if [ $? -ne 0 ]; then echo "Error: Could not get the configration flags of the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "$tmp" != " 0x1" ]; then echo "Error: Unexpected configuration flags: $tmp; expected 0x1." echo "TPM Logfile:" cat $logfile exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi # Start the TPM again; have the keyfile removed run_swtpm ${SWTPM_INTERFACE} \ --key file=$binkeyfile,mode=aes-cbc,format=binary,remove \ --log file=$logfile \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_file_gone ${binkeyfile} 4; then echo "Error: Keyfile $binkeyfile was not removed by ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Saving the volatile state failed." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_getcap000077500000000000000000000041711421141172300173640ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-getcap" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Get the capabilities flags from the TPM act=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -c) if [ $? -ne 0 ]; then echo "Error: Could not get the capability flags of the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after getting capabilities." exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_hashing000077500000000000000000000120131421141172300175340ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-hashing" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM2 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit before the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e ) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (1): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: The hash command failed." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE}'\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') # disregard the update counter using a regex comparison exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 .. 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [[ "$RES" =~ "$exp" ]]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset the establishment bit is not possible via a command # So we do it directly here in locality 3 run_swtpm_ioctl ${SWTPM_INTERFACE} -r 3 if [ $? -ne -0 ]; then echo "Error: Could not reset establishment bit in locality 3" exit 1 fi # Check the TPM Established bit after the reset RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (3): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # back to locality 0 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: Could not set the locality to 0." exit 1 fi # Read from a file dd if=/dev/zero bs=1024 count=1024 2>/dev/null| \ run_swtpm_ioctl ${SWTPM_INTERFACE} -h - swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') # disregard the update counter using a regex comparison exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 .. 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 27 7e de f1 02 56 46 5d 8e 71 65 38 3f d3 63 c9 8a be 89 e2 90 2e 4d 3a 2b 3a 30 80 2f 28 af 19' if [[ "$RES" =~ "$exp" ]]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_hashing2000077500000000000000000000127031421141172300176240ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-hashing2" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Startup the TPM RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit before the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (1): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: The hash command failed." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') # disregard the update counter using a regex comparison exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 .. 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [[ "$RES" =~ "$exp" ]]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset the establishment bit; we switch to locality 0 and reset via locality 3 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: Could not set locality 0" exit 1 fi for ((l = 0; l <= 2; l++)); do # Resetting via locality 2 must fail ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -r $l 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could reset the establishment bit via locality $l" exit 1 fi exp="TPM result from PTM_RESET_TPMESTABLISHED: 0x3d" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi done # Resetting via locality 3 must work run_swtpm_ioctl ${SWTPM_INTERFACE} -r 3 if [ $? -ne 0 ]; then echo "Error: Could not reset the establishment bit via locality 3" exit 1 fi # Check the TPM Established bit after the reset RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (3): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Read from a file dd if=/dev/zero bs=1024 count=1024 2>/dev/null| \ run_swtpm_ioctl ${SWTPM_INTERFACE} -h - swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') # disregard the update counter using a regex comparison exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 .. 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 27 7e de f1 02 56 46 5d 8e 71 65 38 3f d3 63 c9 8a be 89 e2 90 2e 4d 3a 2b 3a 30 80 2f 28 af 19' if [[ "$RES" =~ "$exp" ]]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_hashing3000077500000000000000000000066121421141172300176270ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-hashing3" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # We do NOT need to startup the TPM; Hashing will affect PCR 0 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Check the TPM Established bit before the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 0' if [ "$RES" != "$exp" ]; then echo "Error (1): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Hash run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: The hash command failed." exit 1 fi # Startup the TPM2 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0C\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 0 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x01\x00\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 14 00 00 00 01 00 0b 03 01 00 00 00 00 00 01 00 20 34 0a 23 3f ac 4c a0 14 98 6e 45 dd 95 ec 77 6a 7a 3f 86 a2 10 74 f4 3a 43 90 c5 b8 c3 ab ea f4' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(0)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established bit from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_init000077500000000000000000000052331421141172300170640ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-init" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null if has_seccomp_support "${SWTPM_EXE}"; then SWTPM_TEST_SECCOMP_OPT="--seccomp action=none" fi run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Init the TPM again but make its state file inaccessible; this only # works if the TPM runs as non-rootchmod 000 "${STATE_FILE}" if [ "$(id -u)" != "0" ]; then chmod 000 "${STATE_FILE}" run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -eq 0 ]; then echo "Error: Unexpected initialization success of the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." exit 1 fi chmod 664 "${STATE_FILE}" # Init the TPM again; now with state file accessible again run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi sleep 0.5 kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi fi check_seccomp_profile "${SWTPM_EXE}" ${SWTPM_PID} 0 if [ $? -ne 0 ]; then exit 1 fi # Shut down run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_locality000077500000000000000000000077241421141172300177500ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-locality" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Set locality 4 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 4 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 4." exit 1 fi # Set illegal locality 5 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 5 if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM accepted locality 5." exit 1 fi # Set locality 0 on the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -l 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 0." exit 1 fi # In locality 2 we can reset PCR 20 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 2 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 2." exit 1 fi # Need to set locality 0 or 3 for TPM2_Startup to work... # TPM_Startup for TPM 1.2 worked in all localities run_swtpm_ioctl ${SWTPM_INTERFACE} -l 3 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 3." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # In locality 2 we can reset PCR 20 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 2 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 2." exit 1 fi # Reset PCR 20 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x1b\x00\x00\x01\x3d\x00\x00\x00\x14\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00') exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could not reset PCR 20 in locality 2" echo "expected: $exp" echo "received: $RES" exit 1 fi # In locality 1 we can NOT reset PCR 20 run_swtpm_ioctl ${SWTPM_INTERFACE} -l 1 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not accept locality 1." exit 1 fi # Reset PCR 20 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x1b\x00\x00\x01\x3d\x00\x00\x00\x14\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00') exp=' 80 01 00 00 00 0a 00 00 09 07' if [ "$RES" != "$exp" ]; then echo "Error: Could reset PCR 20 in locality 1" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut down TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_migration_key000077500000000000000000000170721421141172300207660ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. # set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-test-tpm2-migration-key}" SWTPM_DEV_NAME=/dev/${VTPM_NAME} MIGRATION_PASSWORD="migration" VOLATILESTATE=${TESTDIR}/data/migkey1/tpm2-volatilestate.bin SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=$SWTPM_PID if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $migpwdfile $volatilestatefile $tpmstatedir $logfile } trap "cleanup" EXIT tpmstatedir=$(mktemp -d) if [ -z "$tpmstatedir" ]; then echo "Could not create temporary directory." exit 1 fi migpwdfile=$(mktemp) if [ -z "$migpwdfile" ]; then echo "Could not create temporary file." exit 1 fi echo -n "$MIGRATION_PASSWORD" > $migpwdfile volatilestatefile=$(mktemp) if [ -z "$volatilestatefile" ]; then echo "Could not create temporary file." exit 1 fi logfile=$(mktemp) SWTPM_CMD_UNIX_PATH=${tpmstatedir}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${tpmstatedir}/unix-ctrl.sock [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common # make a backup of the volatile state export TPM_PATH=$tpmstatedir cp ${TESTDIR}/data/tpm2state1/* $TPM_PATH rm -f ${logfile} run_swtpm ${SWTPM_INTERFACE} \ --log file=${logfile} \ --tpm2 \ --migration-key pwdfile=$migpwdfile,remove=false,kdf=sha512 kill_quiet -0 $SWTPM_PID if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Initializing the ${SWTPM_INTERFACE} TPM failed." exit 1 fi kill_quiet -0 $SWTPM_PID 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 ECHO=$(which echo) if [ -z "$ECHO" ]; then echo "Could not find NON-bash builtin echo tool." exit 1 fi # Read PCR 10 (from pcrextend -ha 10 -ic test) RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' 100) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state into a file run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $volatilestatefile if [ $? -ne 0 ]; then echo "Error: Could not save the volatile state to ${volatilestatefile}." exit 1 fi if [ ! -r $volatilestatefile ]; then echo "Error: Volatile state file $volatilestatefile does not exist." exit 1 fi size=$(get_filesize $volatilestatefile) expsize="^([5689][0-9]{3})$" if ! [[ $size =~ $expsize ]]; then echo "Error: Unexpected size of volatile state file." echo " Expected file with size of $expsize, found $size bytes." exit 1 fi tmp=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -g | cut -d":" -f2) if [ $? -ne 0 ]; then echo "Error: Could not get the configration flags of the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ "$tmp" != " 0x2" ]; then echo "Error: Unexpected configuration flags: $tmp; expected 0x2." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s echo "Test 1: Ok" # Start the vTPM again and load the encrypted volatile state into it rm -f ${logfile} run_swtpm ${SWTPM_INTERFACE} \ --log file=${logfile} \ --tpm2 \ --migration-key pwdfile=$migpwdfile,remove=false,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 $SWTPM_PID if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --stop # Do NOT init the TPM now; first load volatile state # load the encrypted volatile state into it run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $volatilestatefile if [ $? -ne 0 ]; then echo "Error: Could not load encrypted volatile state into TPM." echo "swtpm logfile: " cat $logfile exit 1 fi # Now init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Initializing the ${SWTPM_INTERFACE} TPM failed." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 10 RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' 100) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 2: Ok" # Start the vTPM again and load the encrypted volatile state into it # This time we make this fail since we don't provide the migration key rm -f ${logfile} run_swtpm ${SWTPM_INTERFACE} \ --log file=${logfile} \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 $SWTPM_PID if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Do NOT init the TPM now; first load volatile state run_swtpm_ioctl ${SWTPM_INTERFACE} --stop # load the encrypted volatile state into it # This will not work; the TPM writes the data into the volatile state file # and validates it ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $volatilestatefile 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could load encrypted volatile state into TPM." cat $logfile exit 1 fi exp="TPM result from PTM_SET_STATEBLOB: 0xd" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi rm -f ${TPM_PATH}/tpm2-00.volatilestate echo "Test 3: Ok" # In this test we now feed it an encrypted volatile state # Start the vTPM again and load the encrypted volatile state into it rm -f ${logfile} run_swtpm ${SWTPM_INTERFACE} \ --log file=${logfile} \ --tpm2 \ --migration-key pwdfile=$migpwdfile,remove=true,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 $SWTPM_PID if [ $? -ne 0 ]; then echo "Error: TPM did not start." cat $logfile exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --stop # load the encrypted volatile state into it run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $VOLATILESTATE if [ $? -ne 0 ]; then echo "Error: Could not load encrypted volatile state into TPM." exit 1 fi # Now init the TPM; this must work run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 10 RES=$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' 100) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi echo "Test 4: Ok" swtpm-0.6.3/tests/_test_tpm2_print_capabilities000077500000000000000000000043631421141172300217710ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} PATH=$ROOT/src/swtpm:$PATH [ "${SWTPM_IFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common msg="$(${SWTPM_EXE} ${SWTPM_IFACE} --tpm2 --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities" echo "${msg}" exit 1 fi if has_seccomp_support "${SWTPM_EXE}"; then seccomp='"cmdarg-seccomp", ' fi if [ "${SWTPM_IFACE}" != "cuse" ]; then noncuse='"tpm-send-command-header", "flags-opt-startup", ' fi # The rsa key size reporting is variable, so use a regex exp='\{ "type": "swtpm", "features": \[ '${noncuse}${seccomp}'"cmdarg-key-fd", "cmdarg-pwd-fd"(, "rsa-keysize-1024")?(, "rsa-keysize-2048")?(, "rsa-keysize-3072")? \] \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_IFACE} TPM to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 1: OK" msg="$(${SWTPM_SETUP} --tpm2 --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities" echo "${msg}" exit 1 fi # The are some variable parameters at the end, use regex exp='\{ "type": "swtpm_setup", "features": \[ "cmdarg-keyfile-fd", "cmdarg-pwdfile-fd", "tpm12-not-need-root"(, "tpm2-rsa-keysize-2048")?(, "tpm2-rsa-keysize-3072")? \] \}' if ! [[ ${msg} =~ ${exp} ]]; then echo "Unexpected response from ${SWTPM_SETUP} to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 2: OK" # SWTPM_CERT may be run by valgrind if [ -x "$(type -P $(echo "${SWTPM_CERT}" | cut -d" " -f1) )" ]; then msg="$(${SWTPM_CERT} --tpm2 --print-capabilities 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not pass --print-capabilities to ${SWTPM_CERT}" echo "${msg}" exit 1 fi exp='{ "type": "swtpm_cert", "features": [ "cmdarg-signkey-pwd", "cmdarg-parentkey-pwd" ] }' if [ "${msg}" != "${exp}" ]; then echo "Unexpected response from ${SWTPM_CERT} to --print-capabilities:" echo "Actual : ${msg}" echo "Expected : ${exp}" exit 1 fi echo "Test 3: OK" else echo "Test 2: SKIP -- ${SWTPM_CERT} not found or not an executable" fi exit 0 swtpm-0.6.3/tests/_test_tpm2_probe000077500000000000000000000051001421141172300172210ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-probe" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi if [ "${SWTPM_INTERFACE}" != "cuse" ]; then run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM" exit 1 fi fi # Open access to the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Before TPM_INIT: Read PCR 17 -- this gives a fatal error # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 0a 00 00 01 01' if [ "$RES" != "$exp" ]; then echo "Error: Before TPM_INIT: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Read PCR 17 -- this should give TPM_INVALID_POSTINIT swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 0a 00 00 01 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi check_seccomp_profile "${SWTPM_EXE}" "${SWTPM_PID}" 2 if [ $? -ne 0 ]; then exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_resume_volatile000077500000000000000000000131301421141172300213130ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME=${vtpm-test-tpm2-resume-volatile:-VTPM_NAME} SWTPM_DEV_NAME="/dev/${VTPM_NAME}" SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} tpmstatedir="$(mktemp -d)" if [ -z "$tpmstatedir" ]; then echo "Could not create temporary directory" exit 1 fi SWTPM_CMD_UNIX_PATH=${tpmstatedir}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${tpmstatedir}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $tpmstatedir } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common export TPM_PATH=$tpmstatedir # copy all the state files cp ${TESTDIR}/data/tpm2state1/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: CUSE TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the CUSE TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: CUSE TPM not running anymore after INIT." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 10 (from pcrextend -ha 10 -ic test) RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the CUSE TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s echo "Test 1: Ok" # 2nd test: with encrypted state # copy all the state files cp ${TESTDIR}/data/tpm2state2/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} \ --tpm2 \ --key pwdfile=${TESTDIR}/data/tpm2state2/pwdfile.txt,kdf=sha512 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: CUSE TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: CUSE TPM initialization failed." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: CUSE TPM not running anymore after INIT." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 if [ $? -ne 0 ]; then echo "Error: Could not open command interface." ext 1 fi # Read PCR 10 (from pcrextend -ha 10 -ic test) RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the CUSE TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the CUSE TPM." exit 1 fi echo "Test 2: Ok" # 3rd test: with encrypted state using aes-256-cbc # copy all the state files cp ${TESTDIR}/data/tpm2state2b/* ${TPM_PATH} run_swtpm ${SWTPM_INTERFACE} \ --tpm2 \ --key pwdfile=${TESTDIR}/data/tpm2state2b/pwdfile.txt,mode=aes-256-cbc display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: CUSE TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: CUSE TPM initialization failed." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: CUSE TPM not running anymore after INIT." exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 if [ $? -ne 0 ]; then echo "Error: Could not open command interface." ext 1 fi # Read PCR 10 (from pcrextend -ha 10 -ic test) RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the CUSE TPM write the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the CUSE TPM." exit 1 fi echo "Test 3: Ok" swtpm-0.6.3/tests/_test_tpm2_save_load_encrypted_state000077500000000000000000000252751421141172300233430ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-test-tpm2-save-load-encrypted-state}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate KEY=1234567890abcdef1234567890abcdef MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock keyfile=$(mktemp) logfile=$(mktemp) echo "$KEY" > $keyfile function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -f $keyfile $logfile rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --key file=$keyfile,mode=aes-cbc,format=hex \ --log file=$logfile \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM (SU_CLEAR) swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Could not hash the data." echo "TPM Logfile:" cat $logfile exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_PERMANENT_STATE_FILE ]; then echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write volatile state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # we will use our own volatile state rm -f $VOLATILE_STATE_FILE $STATE_FILE # Stop the TPM; this will not shut it down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} --stop kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # load state into the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load permanent state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load volatile state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "TPM Init failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM2_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM write the volatile state to a file." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Test 1: Ok" # This time start we start the TPM with a wrong state encryption key # (key used as password) and try to start it. It has to fail and # the state must not have been modified. # volatile state file does not exist sha1_volatile=$(get_sha1_file "${VOLATILE_STATE_FILE}") sha1_permanent=$(get_sha1_file "${STATE_FILE}") echo "sha1(volatile) : $sha1_volatile" echo "sha1(permanent): $sha1_permanent" run_swtpm ${SWTPM_INTERFACE} \ --key pwdfile=$keyfile \ --log file=$logfile \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -i 2>&1)" if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization should have failed." echo "TPM Logfile:" cat $logfile exit 1 fi exp="TPM result from PTM_INIT: 0x101" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "${sha1_volatile}" != "$(get_sha1_file "${VOLATILE_STATE_FILE}")" ]; then echo "Error: Volatile state file was modified during failed init." exit 1 fi if [ "${sha1_permanent}" != "$(get_sha1_file "${STATE_FILE}")" ]; then echo "Error: Permanent state file was modified during failed init." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # shut it down echo "Test 2: Ok" # This time start we start the TPM with a wrong state encryption key # (key used as password) and try to start it. It has to fail and # the state must not have been modified. # volatile state file does not exist sha1_volatile=$(get_sha1_file "${VOLATILE_STATE_FILE}") sha1_permanent=$(get_sha1_file "${STATE_FILE}") echo "sha1(volatile) : $sha1_volatile" echo "sha1(permanent): $sha1_permanent" # we need a 256bit key echo "${KEY}${KEY}" > $keyfile run_swtpm ${SWTPM_INTERFACE} \ --key pwdfile=$keyfile,mode=aes-256-cbc \ --log file=$logfile \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -eq 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM initialization should have failed." echo "TPM Logfile:" cat $logfile exit 1 fi if ! wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after failed INIT." echo "TPM Logfile:" cat $logfile exit 1 fi if [ "${sha1_volatile}" != "$(get_sha1_file "${VOLATILE_STATE_FILE}")" ]; then echo "Error: Volatile state file was modified during failed init." exit 1 fi if [ "${sha1_permanent}" != "$(get_sha1_file "${STATE_FILE}")" ]; then echo "Error: Permanent state file was modified during failed init." exit 1 fi echo "Test 3: Ok" # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_save_load_state000077500000000000000000000163041421141172300212570ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-tpm2-test-save-load-state}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock logfile=$(mktemp) function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -f $logfile rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --log file=$logfile,level=20 \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." echo "TPM Logfile:" cat $logfile exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_PERMANENT_STATE_FILE ]; then echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write volatile state file $MY_VOLATILE_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # we will use our own volatile state rm -f $VOLATILE_STATE_FILE $STATE_FILE # Stop the TPM; this will not shut it down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # load state into the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load permanent state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load volatile state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "TPM Init failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read the PCR again ... RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (3) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi cat $logfile echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_save_load_state_da_timeout000077500000000000000000000240361421141172300234720ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="${VTPM_NAME:-vtpm-tpm2-test-save-load-state-da-timeout}" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate MY_VOLATILE_STATE_FILE=$TPM_PATH/my.volatilestate MY_PERMANENT_STATE_FILE=$TPM_PATH/my.permanent SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock logfile=$(mktemp) function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -f $logfile rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} \ --log file=$logfile,level=20 \ --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." echo "TPM Logfile:" cat $logfile exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." echo "TPM Logfile:" cat $logfile exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Create an NVRAM location: nvdefinespace -hi o -ha 01000000 -pwdn nnn -sz 16 -at da swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x30\x00\x00\x01\x2a\x40\x00\x00\x01\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x03\x6e\x6e\x6e\x00\x0e\x01\x00\x00\x00\x00\x0b\x00\x04\x00\x04\x00\x00\x00\x10') exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_DefineSpace()" echo "expected: $exp" echo "received: $RES" exit 1 fi sleep 1 # TPM2_NV_Write with good password 'nnn' and bad password 'nn' NVWRITE_GOOD='\x80\x02\x00\x00\x00\x2a\x00\x00\x01\x37\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0c\x40\x00\x00\x09\x00\x00\x00\x00\x03\x6e\x6e\x6e\x00\x04\x74\x65\x73\x74\x00\x00' NVWRITE_BAD='\x80\x02\x00\x00\x00\x29\x00\x00\x01\x37\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0b\x40\x00\x00\x09\x00\x00\x00\x00\x02\x6e\x6e\x00\x04\x74\x65\x73\x74\x00\x00' # Write some data into the NVRAM area: nvwrite -ha 01000000 -ic test -pwdn nnn # Due to -at da being used on TPM2_NV_DefineSpace, the first time the command will request a retry for ((i = 0; i < 2; i++)); do swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ $i -eq 1 ] && [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_Write()" echo "expected: $exp" echo "received: $RES" exit 1 fi done # Set the dictionary attack parameters: dictionaryattackparameters -lr 6 -nrt 6 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x02\x00\x00\x00\x27\x00\x00\x01\x3a\x40\x00\x00\x0a\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x06') exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result fron TPM2_DictionaryAttackParameters()" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send TPM2_NV_Write with wrong password swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_BAD}) exp=' 80 01 00 00 00 0a 00 00 09 8e' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_Write() with bad password" echo "expected: $exp" echo "received: $RES" exit 1 fi timenow=$(date +%s) timeout=$((timenow + 6)) # TPM2_NV_Write with good password must now fail until $timeout while :; do timenow=$(date +%s) echo "Writing with good password failed due to lockout until $timeout - now is $timenow." swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) exp=' 80 01 00 00 00 0a 00 00 09 21' # busy systems may run the above at >= $timeout and get an unexpected result; check time again timenow=$(date +%s) if [ "$RES" != "$exp" ] && [ $timenow -lt $timeout ]; then echo "Error: Did not get expected failure from TPM2_NV_Write() with good password. Lockout should be enabled." echo "expected: $exp" echo "received: $RES" exit 1 fi [ $timenow -ge $timeout ] && break sleep 1 done sleep 1 timenow_after=$(date +%s) echo "Time is now ${timenow_after} -- trying with good password should work now." # Now writing with the good password must work again swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_Write() with good password" echo "expected: $exp" echo "received: $RES" # OS X special check if [ $timenow_after -lt $timenow ]; then echo "Time went backwards..." exit 77 fi exit 1 fi # Againg cause lockout: Send TPM2_NV_Write with wrong password swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_BAD}) exp=' 80 01 00 00 00 0a 00 00 09 8e' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_Write() with bad password" echo "expected: $exp" echo "received: $RES" exit 1 fi timenow=$(date +%s) timeout=$((timenow + 6)) # Save the state and restore it and then try to poll again run_swtpm_ioctl ${SWTPM_INTERFACE} --save permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write permanent state file $MY_PERMANENT_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_PERMANENT_STATE_FILE ]; then echo "Error: Permanent state file $MY_PERMANENT_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --save volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Error: Could not write volatile state file $MY_VOLATILE_STATE_FILE." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -r $MY_VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $MY_VOLATILE_STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "Saved volatile state." # we will use our own volatile state rm -f $VOLATILE_STATE_FILE $STATE_FILE # Stop the TPM; this will not shut it down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error (2): ${SWTPM_INTERFACE} TPM is not running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi # load state into the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} --load permanent $MY_PERMANENT_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load permanent state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded permanent state." run_swtpm_ioctl ${SWTPM_INTERFACE} --load volatile $MY_VOLATILE_STATE_FILE if [ $? -ne 0 ]; then echo "Could not load volatile state into vTPM" echo "TPM Logfile:" cat $logfile exit 1 fi echo "Loaded volatile state." #ls -l $(dirname $MY_VOLATILE_STATE_FILE)/* #sha1sum $(dirname $MY_VOLATILE_STATE_FILE)/* # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "TPM Init failed." echo "TPM Logfile:" cat $logfile exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." echo "TPM Logfile:" cat $logfile exit 1 fi # TPM2_NV_Write with good password must now fail until $timeout while :; do timenow=$(date +%s) echo "Writing with good password failed due to lockout until $timeout - now is $timenow." swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) exp=' 80 01 00 00 00 0a 00 00 09 21' # busy systems may run the above at >= $timeout and get an unexpected result; check time again timenow=$(date +%s) if [ "$RES" != "$exp" ] && [ $timenow -lt $timeout ]; then echo "Error: Did not get expected failure from TPM2_NV_Write() with good password. Lockout should be enabled." echo "expected: $exp" echo "received: $RES" exit 1 fi [ $timenow -ge $timeout ] && break sleep 1 done sleep 1 timenow_after=$(date +%s) echo "Time is now $timenow_after -- trying with good password should work now." # Now writing with the good password must work again swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} ${NVWRITE_GOOD}) exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_NV_Write() with good password" echo "expected: $exp" echo "received: $RES" # OS X special check if [ $timenow_after -lt $timenow ]; then echo "Time went backwards..." exit 77 fi exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." echo "TPM Logfile:" cat $logfile exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." echo "TPM Logfile:" cat $logfile exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." echo "TPM Logfile:" cat $logfile exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_savestate000077500000000000000000000111361421141172300201170ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-savestate" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM2 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Extend PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 req='\x80\x02\x00\x00\x00\x41\x00\x00\x01\x82\x00\x00\x00\x0a\x00\x00' req+='\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00' req+='\x0b\x68\x65\x6c\x6c\x6f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' req+='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' req+='\x00' RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} $req) exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_PCR_Extend(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 10 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 15 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 c3 ba a5 62 69 08 26 72 c3 db 3d 11 0a 10 74 a1 a7 a6 ea 43 e8 82 16 1a af 4b ea a6 83 17 e4 b8' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Shutdown(SU_STATE) RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x45\x00\x01') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_Shutdown(SU_STATE)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Startup(SU_STATE) the TPM2 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x01') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_State)" echo "expected: $exp" echo "received: $RES" exit 1 fi swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 10 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 19 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 c3 ba a5 62 69 08 26 72 c3 db 3d 11 0a 10 74 a1 a7 a6 ea 43 e8 82 16 1a af 4b ea a6 83 17 e4 b8' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM2_PCR_Read(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_setbuffersize000077500000000000000000000070661421141172300210070ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-setbuffersize" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall OUTFILE=$TPM_PATH/output VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Check the buffer size run_swtpm_ioctl ${SWTPM_INTERFACE} -b 0 > ${OUTFILE} if [ $? -ne 0 ]; then echo "Error: Could not get the buffersize of the ${SWTPM_INTERFACE} TPM." exit 1 fi cat ${OUTFILE} if [ -z "$(grep "TPM buffersize" ${OUTFILE} | grep 4096)" ]; then echo "Error: The TPM buffersize of the ${SWTPM_INTERFACE} TPM is not 4096." exit 1 fi # set the buffer size -- it's not going to change but command must not fail run_swtpm_ioctl ${SWTPM_INTERFACE} -b 4000 > ${OUTFILE} if [ $? -ne 0 ]; then echo "Error: Could not set the buffersize of the ${SWTPM_INTERFACE} TPM." exit 1 fi cat ${OUTFILE} if [ -z "$(grep "TPM buffersize" ${OUTFILE} | grep 4000)" ]; then echo "Error: Could not set the buffersize of the ${SWTPM_INTERFACE} TPM to 4000." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Set the buffer size -- should fail ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -b 4096 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could set the buffersize while the ${SWTPM_INTERFACE} TPM is running." exit 1 fi exp="TPM result from PTM_SET_BUFFERSIZE: 0xa" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi # Startup the TPM2 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Read the Buffer sizes; we want to see '4000' (0xfa0) in the buffer sizes now swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x16\x00\x00\x01\x7a\x00\x00\x00\x06\x00\x00\x01\x1e\x00\x00\x00\x02') exp=' 80 01 00 00 00 23 00 00 00 00 01 00 00 00 06 00 00 00 02 00 00 01 1e 00 00 0f a0 00 00 01 1f 00 00 0f a0' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM2_GetCapability()" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_swtpm_bios000077500000000000000000000076241421141172300203150ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-swtpm-bios" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate PID_FILE=$TPM_PATH/SWTPM.pid SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 --tpmstate dir=$TPM_PATH --pid file=$PID_FILE display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi if wait_for_file ${PID_FILE} 4; then echo "Error: ${SWTPM_INTERFACE} TPM did not write pidfile." exit 1 fi PIDF="$(cat $PID_FILE)" if [ "$PIDF" != "${SWTPM_PID}" ]; then echo "Error: ${SWTPM_INTERFACE} TPM wrote pid $PIDF, but found ${SWTPM_PID}." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi if ! wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -o 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n --cs 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not self-test the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi # will NOT work -- we get error output in $res res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ $ret -ne 128 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret." exit 1 fi # will NOT work (wrong device) -- we get error output in $res if [ "${SWTPM_INTERFACE}" == "cuse" ]; then res=$($SWTPM_BIOS --tpm-device /dev/${VTPM_NAME}123--tpm2 -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on wrong device." exit 1 fi if [ $ret -ne 255 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 255, had $ret." exit 1 fi fi # RESET TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # must work res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 --cs -u 2>&1) if [ $? -ne 0 ] || [ -n "$res" ]; then echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM." exit 1 fi # will NOT work -- we get error output in $res res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1) ret=$? if [ $ret -eq 0 ] || [ -z "$res" ]; then echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM." exit 1 fi if [ $ret -ne 128 ]; then echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_volatilestate000077500000000000000000000147541421141172300210110ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. # set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-volatilestate" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_CMD_UNIX_PATH=$TPM_PATH/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=$TPM_PATH/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00') exp=' 80 01 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." exit 1 fi # Read PCR 17 # length CC count hashalg sz swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi # Start the TPM again run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check that the TPM Established bit is still set RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 fc a5 d6 49 bf b0 c9 22 fd 33 0f 79 b2 00 43 28 9d af d6 0d 01 a4 c4 37 3c f2 8a db 56 c9 b4 54' if [ "$RES" != "$exp" ]; then echo "Error: (3) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check that the TPM Established bit is still set RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm2_wrongorder000077500000000000000000000056641421141172300203210ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm2-wrongorder" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --tpm2 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Get the established bit before the TPM has been initialized # This should not work if [ ${SWTPM_INTERFACE} != "cuse" ]; then run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM." exit 1 fi fi ERR="$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e 2>&1)" if [ $? -eq 0 ]; then echo "Error: Could get established bit from ${SWTPM_INTERFACE} TPM before init." exit 1 fi exp="TPM result from PTM_GET_TPMESTABLISHED: 0xa" if [ "$ERR" != "$exp" ]; then echo "Error: Unexpected error message" echo "Received: $ERR" echo "Expected: $exp" exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM must have crashed." exit 1 fi # Open access to the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Read PCR 17 # length CC count hashalg sz RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02') exp=' 80 01 00 00 00 0a 00 00 01 01' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi exec 100>&- kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM must have crashed." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_tpm_probe000077500000000000000000000041611421141172300171450ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-tpm-probe" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Open access to the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Before TPM_INIT: Read PCR 17 -- this gives a TPM_FAIL RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 0a 00 00 00 09' if [ "$RES" != "$exp" ]; then echo "Error: Before TPM_INIT: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i # Read PCR 17 -- this should give TPM_INVALID_POSTINIT swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 0a 00 00 00 26' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi check_seccomp_profile "${SWTPM_EXE}" "${SWTPM_PID}" 2 if [ $? -ne 0 ]; then exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_volatilestate000077500000000000000000000134321421141172300200370ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-volatilestate" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Startup the TPM swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01') exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -h 1234 if [ $? -ne 0 ]; then echo "Error: Hash command did not work." exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check the TPM Established bit after the hashing RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Shut the TPM down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi # Start the TPM again run_swtpm ${SWTPM_INTERFACE} display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check that the TPM Established bit is still set RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state again run_swtpm_ioctl ${SWTPM_INTERFACE} -v if [ $? -ne 0 ]; then echo "Error: Could not have the ${SWTPM_INTERFACE} TPM store the volatile state to a file." exit 1 fi if [ ! -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE does not exist." exit 1 fi # Send a new TPM_Init run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi # Volatile state must have been removed by TPM now if [ -r $VOLATILE_STATE_FILE ]; then echo "Error: Volatile state file $VOLATILE_STATE_FILE still exists." exit 1 fi # Read the PCR again ... swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 1e 00 00 00 00 97 e9 76 e4 f2 2c d6 d2 4a fd 21 20 85 ad 7a 86 64 7f 2a e5' if [ "$RES" != "$exp" ]; then echo "Error: (2) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Check that the TPM Established bit is still set RES=$(run_swtpm_ioctl ${SWTPM_INTERFACE} -e) if [ $? -ne 0 ]; then echo "Error: Could not get the TPM Established flag from the ${SWTPM_INTERFACE} TPM." exit 1 fi exp='tpmEstablished is 1' if [ "$RES" != "$exp" ]; then echo "Error (2): TPM Established flag has wrong value." echo "expected: $exp" echo "received: $RES" exit 1 fi # Final shut down exec 100>&- run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/_test_wrongorder000077500000000000000000000054011421141172300173440ustar00rootroot00000000000000#!/bin/bash # For the license, see the LICENSE file in the root directory. #set -x ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} VTPM_NAME="vtpm-test-wrongorder" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall LOG_FILE=$TPM_PATH/tpm-00.log VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse} function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == cuse ] && source ${TESTDIR}/test_cuse source ${TESTDIR}/common source ${TESTDIR}/test_common rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null run_swtpm ${SWTPM_INTERFACE} --log file=$LOG_FILE,level=20 display_processes_by_name "$SWTPM" kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi if [ "${SWTPM_INTERFACE}" != "cuse" ]; then run_swtpm_ioctl ${SWTPM_INTERFACE} --stop if [ $? -ne 0 ]; then echo "Error: Could not stop the ${SWTPM_INTERFACE} TPM" exit 1 fi fi # Get the established bit before the TPM has been initialized # This should not work run_swtpm_ioctl ${SWTPM_INTERFACE} -e if [ $? -eq 0 ]; then echo "Error: Could get established bit from ${SWTPM_INTERFACE} TPM before init." exit 1 fi kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM must have crashed." exit 1 fi # Read PCR 17 -- this should give a fatal error response swtpm_open_cmddev ${SWTPM_INTERFACE} 100 RES=$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11') exp=' 00 c4 00 00 00 0a 00 00 00 09' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi exec 100>&- kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM must have crashed." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi check_logfile_patterns_level_20 $LOG_FILE rm -f $LOG_FILE echo "OK" exit 0 swtpm-0.6.3/tests/common000066400000000000000000000411301421141172300152420ustar00rootroot00000000000000 SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-${ROOT}/src/swtpm/${SWTPM}} SWTPM_IOCTL=${SWTPM_IOCTL:-${ROOT}/src/swtpm_ioctl/swtpm_ioctl} SWTPM_BIOS=${SWTPM_BIOS:-${ROOT}/src/swtpm_bios/swtpm_bios} SWTPM_SETUP=${SWTPM_SETUP:-${ROOT}/src/swtpm_setup/swtpm_setup} SWTPM_CERT=${SWTPM_CERT:-${ROOT}/src/swtpm_cert/swtpm_cert} ECHO=$(type -P echo) case "$(uname -s)" in Darwin) CERTTOOL=gnutls-certtool;; *) CERTTOOL=certtool;; esac # Note: Do not use file descriptors above 127 due to OpenBSD. # Kill a process quietly # @1: signal, e.g. -9 # @2: pid function kill_quiet() { local sig="$1" local pid="$2" bash -c "kill $sig $pid &>/dev/null" return $? } # Wait for a regular file to appear and for it to have > 0 bytes # # @1: filename # @2: timeout in seconds function wait_for_file() { local filename="$1" local timeout="$2" local loops=$((timeout * 10)) loop for ((loop=0; loop/dev/tcp/${host}/${port}) &>/dev/null [ $? -eq 0 ] && return 1 sleep 0.1 done return 0 } # Wait for a server socket to disappear # # @1: port # @2: host # @3: timeout in seconds function wait_serversocket_gone() { local port="$1" local host="$2" local timeout="$3" local loops=$((timeout * 10)) loop for ((loop=0; loop/dev/tcp/${host}/${port}) &>/dev/null [ $? -eq 0 ] || return 1 sleep 0.1 done return 0 } # Wait for a TCP port to open for listening # @1: port # @2: id of process to open port # @3: timeout in seconds function wait_port_open() { local port=$1 local pid=$2 local timeout=$3 local loops=$((timeout * 10)) loop local NETSTAT=$(type -P netstat) for ((loop = 0; loop < loops; loop++)); do if [ -n "$NETSTAT" ]; then if [ -n "$(netstat -naptl 2>/dev/null | grep "LISTEN" | grep " $pid/" | grep ":$port ")" ]; then return 1 fi else if [ -n "$(ss -nptl | grep ",pid=${pid}," | grep ":$port ")" ]; then return 1 fi fi sleep 0.1 done return 0 } # Wait for a TCP listening port to close # @1: port # @2: id of process to close port # @3: timeout in seconds function wait_port_closed() { local port=$1 local pid=$2 local timeout=$3 local loops=$((timeout * 10)) loop local NETSTAT=$(type -P netstat) for ((loop = 0; loop < loops; loop++)); do if [ -n "$NETSTAT" ]; then if [ -z "$(netstat -naptl 2>/dev/null | grep "LISTEN" | grep " $pid/" | grep ":$port ")" ]; then return 1 fi else if [ -z "$(ss -nptl | grep ",pid=${pid}," | grep ":$port ")" ]; then return 1 fi fi sleep 0.1 done return 0 } # Run the swtpm_ioctl command # # @param1: type of interface function run_swtpm_ioctl() { local iface=$1; shift case "${iface}" in cuse) [ -z "${SWTPM_DEV_NAME}" ] && { echo "SWTPM_DEV_NAME not defined" exit 1 } ${SWTPM_IOCTL} $@ ${SWTPM_DEV_NAME} return $? ;; socket+socket|unix+socket) [ -z "${SWTPM_SERVER_NAME}" ] && { echo "SWTPM_SERVER_NAME not defined" exit 1 } [ -z "${SWTPM_SERVER_PORT}" ] && { echo "SWTPM_SERVER_PORT not defined" exit 1 } ${SWTPM_IOCTL} \ --tcp ${SWTPM_SERVER_NAME}:${SWTPM_CTRL_PORT} \ $@ return $? ;; socket+unix|unix+unix) [ -z "${SWTPM_CTRL_UNIX_PATH}" ] && { echo "SWTPM_CTRL_UNIX_PATH not defined" exit 1 } ${SWTPM_IOCTL} \ --unix ${SWTPM_CTRL_UNIX_PATH} \ $@ return $? ;; esac } # Start the swtpm in the background # # @param1: type of interface # @param2.. : parameters to pass to 'swtpm' function run_swtpm() { local iface=$1; shift local swtpm_server_disconnect="" echo "==== Starting swtpm with interfaces ${iface} ====" if [ -z "${SWTPM_SERVER_NO_DISCONNECT}" ]; then swtpm_server_disconnect=",disconnect" fi case "${iface}" in cuse) [ -z "${SWTPM_DEV_NAME}" ] && { echo "SWTPM_DEV_NAME not defined" exit 1 } if wait_chardev_gone ${SWTPM_DEV_NAME} 2; then echo "${SWTPM_DEV_NAME} is still there and may be used." exit 1 fi ${SWTPM_EXE} cuse "$@" ${SWTPM_TEST_SECCOMP_OPT} \ -n ${SWTPM_DEV_NAME##*/} rc=$? if [ $rc -ne 0 ]; then echo "Could not run ${SWTPM_EXE} using ${iface}" exit 1 fi if wait_for_chardev ${SWTPM_DEV_NAME} 2; then echo "$SWTPM_DEV_NAME did not appear" exit 1 fi SWTPM_PID=$(ps aux | grep "cuse" | grep -E " ${SWTPM_DEV_NAME##*/}\$" | grep -v grep | gawk '{print $2}') return $? ;; socket+socket) [ -z "${SWTPM_SERVER_PORT}" ] && { echo "SWTPM_SERVER_PORT not defined" exit 1 } [ -z "${SWTPM_CTRL_PORT}" ] && { echo "SWTPM_CTRL_PORT not defined" exit 1 } if wait_serversocket_gone "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then echo "Port ${SWTPM_SERVER_PORT} is still used" exit 1 fi if wait_serversocket_gone "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then echo "Port ${SWTPM_CTRL_PORT} is still used" exit 1 fi ${SWTPM_EXE} socket "$@" \ ${SWTPM_TEST_SECCOMP_OPT} \ --server type=tcp,port=${SWTPM_SERVER_PORT}${swtpm_server_disconnect} \ --ctrl type=tcp,port=${SWTPM_CTRL_PORT} & rc=$? if [ $rc -ne 0 ]; then echo "Could not run ${SWTPM_EXE} using ${iface}" exit 1 fi SWTPM_PID=$! if wait_for_serversocket "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then echo "Server did not open port ${SWTPM_SERVER_PORT}" kill -9 ${SWTPM_PID} exit 1 fi if wait_for_serversocket "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then echo "Server did not open port ${SWTPM_CTRL_PORT}" kill -9 ${SWTPM_PID} exit 1 fi return 0 ;; socket+unix) [ -z "${SWTPM_SERVER_PORT}" ] && { echo "SWTPM_SERVER_PORT not defined" exit 1 } [ -z "${SWTPM_CTRL_UNIX_PATH}" ] && { echo "SWTPM_CTRL_UNIX_PATH not defined" exit 1 } if wait_serversocket_gone "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then echo "Port ${SWTPM_SERVER_PORT} is still used" exit 1 fi if wait_socketfile_gone "${SWTPM_CTRL_UNIX_PATH}" 2; then echo "Unix socket ${SWTPM_CTRL_UNIX_PATH} is still there" exit 1 fi ${SWTPM_EXE} socket "$@" \ ${SWTPM_TEST_SECCOMP_OPT} \ --server type=tcp,port=${SWTPM_SERVER_PORT}${swtpm_server_disconnect} \ --ctrl type=unixio,path=${SWTPM_CTRL_UNIX_PATH} & rc=$? if [ $rc -ne 0 ]; then echo "Could not run ${SWTPM_EXE} using ${iface}" exit 1 fi [ $rc -ne 0 ] && return $rc SWTPM_PID=$! if wait_for_serversocket "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then echo "Server did not open port ${SWTPM_SERVER_PORT}" kill -9 ${SWTPM_PID} exit 1 fi if wait_for_socketfile ${SWTPM_CTRL_UNIX_PATH} 1; then echo "Server did not create UnixIO socket ${SWTPM_CTRL_UNIX_PATH}" kill -9 ${SWTPM_PID} exit 1 fi return 0 ;; unix+socket) [ -z "${SWTPM_CMD_UNIX_PATH}" ] && { echo "SWTPM_CMD_UNIX_PATH not defined" exit 1 } [ -z "${SWTPM_CTRL_PORT}" ] && { echo "SWTPM_CTRL_PORT not defined" exit 1 } if wait_socketfile_gone "${SWTPM_CMD_UNIX_PATH}" 2; then echo "Unix socket ${SWTPM_CMD_UNIX_PATH} is still there" exit 1 fi if wait_serversocket_gone "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then echo "Port ${SWTPM_CTRL_PORT} is still used" exit 1 fi ${SWTPM_EXE} socket "$@" \ ${SWTPM_TEST_SECCOMP_OPT} \ --server type=unixio,path=${SWTPM_CMD_UNIX_PATH} \ --ctrl type=tcp,port=${SWTPM_CTRL_PORT} & rc=$? if [ $rc -ne 0 ]; then echo "Could not run ${SWTPM_EXE} using ${iface}" exit 1 fi SWTPM_PID=$! if wait_for_socketfile ${SWTPM_CMD_UNIX_PATH} 2; then echo "Server did not create UnixIO socket ${SWTPM_CMD_UNIX_PATH}" kill -9 ${SWTPM_PID} exit 1 fi if wait_for_serversocket "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then echo "Server did not open port ${SWTPM_CTRL_PORT}" kill -9 ${SWTPM_PID} exit 1 fi return 0 ;; unix+unix) [ -z "${SWTPM_CMD_UNIX_PATH}" ] && { echo "SWTPM_CMD_UNIX_PATH not defined" exit 1 } [ -z "${SWTPM_CTRL_UNIX_PATH}" ] && { echo "SWTPM_CTRL_UNIX_PATH not defined" exit 1 } if wait_socketfile_gone "${SWTPM_CMD_UNIX_PATH}" 2; then echo "Unix socket ${SWTPM_CMD_UNIX_PATH} is still there" exit 1 fi if wait_socketfile_gone "${SWTPM_CTRL_UNIX_PATH}" 2; then echo "Unix socket ${SWTPM_CTRL_UNIX_PATH} is still there" exit 1 fi ${SWTPM_EXE} socket "$@" \ ${SWTPM_TEST_SECCOMP_OPT} \ --server type=unixio,path=${SWTPM_CMD_UNIX_PATH} \ --ctrl type=unixio,path=${SWTPM_CTRL_UNIX_PATH} & rc=$? if [ $rc -ne 0 ]; then echo "Could not run ${SWTPM_EXE} using ${iface}" exit 1 fi SWTPM_PID=$! if wait_for_socketfile ${SWTPM_CMD_UNIX_PATH} 2; then echo "Server did not create UnixIO socket ${SWTPM_CMD_UNIX_PATH}" kill -9 ${SWTPM_PID} exit 1 fi if wait_for_socketfile ${SWTPM_CTRL_UNIX_PATH} 1; then echo "Server did not create UnixIO socket ${SWTPM_CTRL_UNIX_PATH}" kill -9 ${SWTPM_PID} exit 1 fi return 0 ;; esac } # Open the command channel/device on fd 100 # # @param1: type of interface # @param2: must be '100' function swtpm_open_cmddev() { local iface=$1; shift [ "$1" != "100" ] && { echo "swtpm_opendev: Filedescriptor must be 100" exit 1 } case "${iface}" in cuse) [ -z "${SWTPM_DEV_NAME}" ] && { echo "SWTPM_DEV_NAME not defined" exit 1 } exec 100<>${SWTPM_DEV_NAME} return $? ;; socket+socket|socket+unix) [ -z "${SWTPM_SERVER_NAME}" ] && { echo "SWTPM_SERVER_NAME not defined" exit 1 } [ -z "${SWTPM_SERVER_PORT}" ] && { echo "SWTPM_SERVER_PORT not defined" exit 1 } # Must first close on OS/X exec 100>&- exec 100<>/dev/tcp/${SWTPM_SERVER_NAME}/${SWTPM_SERVER_PORT} return $? ;; unix+socket|unix+unix) ;; *) echo "swtpm_opendev: unsupported interface $iface" exit 1 esac } # Transmit a command on fd 100 # # @param1: type of interface function swtpm_cmd_tx() { local iface=$1 local cmd_path resp_path cmd_path=$(mktemp) case "${iface}" in cuse) echo -en "$2" > ${cmd_path} cat ${cmd_path} >&100 dd if=/proc/self/fd/100 2>/dev/null | \ od -t x1 -A n | \ tr -s ' ' | \ tr -d '\n' | \ sed 's/ $//g' ;; socket+socket|socket+unix) echo -en "$2" > ${cmd_path} cat ${cmd_path} >&100 cat <&100 | od -t x1 -A n | \ tr -s ' ' | \ tr -d '\n' | \ sed 's/ $//g' ;; unix+socket|unix+unix) echo -en "$2" > ${cmd_path} socat -x -t50 \ FILE:${cmd_path},rdonly \ UNIX-CLIENT:${SWTPM_CMD_UNIX_PATH} 2>&1 | \ sed -n '/^ /p' | \ tail -n1 ;; *) echo "swtpm_opendev: unsupported interface $iface" rm -f ${cmd_path} exit 1 esac rm -f ${cmd_path} } # Transmit a control command on fd 101 # # @param1: type of interface function swtpm_ctrl_tx() { local iface=$1 local ctrl_path resp_path case "${iface}" in socket+socket|unix+socket) $ECHO -en "$2" >&101 cat <&101 | od -t x1 -A n -w128 ;; socket+unix|unix+unix) ctrl_path=$(mktemp) echo -en "$2" > ${ctrl_path} socat -x -t50 \ FILE:${ctrl_path},rdonly \ UNIX-CLIENT:${SWTPM_CTRL_UNIX_PATH} 2>&1 | \ sed -n '/^ /p' | \ tail -n1 rm -f ${ctrl_path} ;; *) echo "swtpm_opendev: unsupported interface $iface" exit 1 esac } # Run swtpm_bios # # @param1: type of interface # @param2 ...: parameters to pass to swtpm_bios function run_swtpm_bios() { local iface=$1 shift case "${iface}" in cuse) [ -z "${SWTPM_DEV_NAME}" ] && { echo "SWTPM_DEV_NAME not defined" exit 1 } ${SWTPM_BIOS} --tpm-device ${SWTPM_DEV_NAME} $@ return $? ;; unix+unix|unix+socket) [ -z "${SWTPM_CMD_UNIX_PATH}" ] && { echo "SWTPM_CMD_UNIX_PATH not defined" exit 1 } ${SWTPM_BIOS} --unix ${SWTPM_CMD_UNIX_PATH} $@ return $? ;; socket+unix|socket+socket) [ -z "${SWTPM_SERVER_PORT}" ] && { echo "SWTPM_SERVER_PORT not defined" exit 1 } ${SWTPM_BIOS} --tcp ${SWTPM_SERVER_NAME}:${SWTPM_SERVER_PORT} $@ return $? ;; *) echo "run_swtpm_bios: unsupported interface $iface" exit 1 esac } # Get the size of a file in bytes # # @1: filename function get_filesize() { if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then stat -c%s $1 else # OpenBSD stat -f%z $1 fi } # Get the file mode bits in octal format # # @1: filename function get_filemode() { if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then stat -c%a $1 else # BSDs stat -f%Lp $1 fi } # Get the file owner uid and gid # # @1: filename function get_fileowner() { if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then stat -c"%u %g" $1 else # BSDs stat -f"%u %g" $1 fi } # Get the SHA1 of a file # # @1: filename function get_sha1_file() { if ! [ -r $1 ]; then echo "[file $1 does not exist]" return fi case "$(uname -s)" in Linux|CYGWIN*) sha1sum $1 | cut -f1 -d" " ;; Darwin) shasum $1 | cut -f1 -d" " ;; *) # OpenBSD sha1 $1 | cut -d "=" -f2 | tr -d " " esac } # Display process that have the same name # # @1: process name to match function display_processes_by_name() { local name="$1" if [ 1 -eq 0 ]; then ps aux | grep "${name}" | grep -v grep fi } # Check whether seccomp support is compiled in # # @1: path to swtpm # # Returns 0 if seccomp is supported, 1 otherwise function has_seccomp_support() { local swtpm_exe="$1" local tmp=$(${swtpm_exe} socket --help | grep -E "\-\-seccomp") [ -n "${tmp}" ] && return 0 return 1 } # Check whether the given process runs with the given seccomp # profile type IF the given swtpm executable has seccomp support # # @1: Path to swtpm executable from which process was started # @2: The process ID # @3: The expected seccomp profile type function check_seccomp_profile() { local swtpm_exe="$1" local swtpm_pid="$2" local profile="$3" local tmp if ! has_seccomp_support "${swtpm_exe}"; then return 0 fi if [ -n "${SWTPM_TEST_SECCOMP_OPT}" ]; then return 0 fi tmp=$(grep -E "^Seccomp" /proc/self/status | cut -d":" -f2 | tr -d '\t') if [ "${tmp}" != "0" ]; then echo "check_seccomp_profile: skipping check since test env." \ "runs with in a seccomp profile overriding --seccomp" return 0 fi tmp=$(grep -E "^Seccomp" /proc/${swtpm_pid}/status | cut -d":" -f2 | tr -d '\t') if [ "${tmp}" != ${profile} ]; then echo "Process ${swtpm_pid} has wrong seccomp profile type" echo "Expected: ${profile}" echo "Actual : ${tmp}" return 1 fi return 0 } # Validate the content of the pid file # @1: Expected PID # @2: pid file filename function validate_pidfile() { local pid="$1" local pidfile="$2" local rpid="$(cat $pidfile)" if [ -z "$rpid" ]; then sleep 0.1 rpid="$(cat $pidfile)" fi if [ "$pid" != "$rpid" ]; then echo "Error: pid file contains unexpected PID value." echo "expected: $pid" echo "actual : $(cat $pidfile)" exit 1 fi } swtpm-0.6.3/tests/create_certs.sh000077500000000000000000000006621421141172300170360ustar00rootroot00000000000000#!/usr/bin/env bash #echo $@ main() { local typ ek dir vmid while [ $# -ne 0 ]; do #echo $1 case "$1" in --type) shift typ="$1" ;; --ek) shift ek="$1" ;; --dir) shift dir="$1" ;; --vmid) shift vmid="$1" ;; --tpm2) ;; esac shift done case "$typ" in ek) echo -n "ek" > ${dir}/ek.cert ;; platform) echo -n "platform" > ${dir}/platform.cert ;; esac } main "$@" swtpm-0.6.3/tests/data/000077500000000000000000000000001421141172300147415ustar00rootroot00000000000000swtpm-0.6.3/tests/data/ecprivek.pem000066400000000000000000000005031421141172300172520ustar00rootroot00000000000000ASN1 OID: prime256v1 -----BEGIN EC PARAMETERS----- BggqhkjOPQMBBw== -----END EC PARAMETERS----- -----BEGIN EC PRIVATE KEY----- MHcCAQEEINoBbt73wFU8ku/qodAP58flsgL94j+FsX6ycP8ts8MKoAoGCCqGSM49 AwEHoUQDQgAEne14S57Dr9tYfw2PtsVoaC0IrHjiEFKihkvMeimuYRVxYkZh5kmZ fwcOIKlGawAo1JhUgA3iYSlLi3ho71aq0g== -----END EC PRIVATE KEY----- swtpm-0.6.3/tests/data/ecpubek.pem000066400000000000000000000002621421141172300170620ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEne14S57Dr9tYfw2PtsVoaC0IrHji EFKihkvMeimuYRVxYkZh5kmZfwcOIKlGawAo1JhUgA3iYSlLi3ho71aq0g== -----END PUBLIC KEY----- swtpm-0.6.3/tests/data/issuercert.pem000066400000000000000000000027251421141172300176420ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEITCCAomgAwIBAgIMWtYHsR4z7cnrzsG6MA0GCSqGSIb3DQEBCwUAMB8xHTAb BgNVBAMTFHN3dHBtLWxvY2FsY2Etcm9vdGNhMB4XDTE4MDQxNzE0NDE1M1oXDTI4 MDQxNDE0NDE1M1owGDEWMBQGA1UEAxMNc3d0cG0tbG9jYWxjYTCCAaIwDQYJKoZI hvcNAQEBBQADggGPADCCAYoCggGBAL+1uBTQ5yVOzAwkgNWxRbsqKLMvxPcRcf8W S70ZSOUu9nvELDvMQPEGE7Y48Qxv2O/XZ8Pa9H6Gupg+uvUBTYnnHBUgJLuXF9YD naXaS1KY1dHOVOZQygFySq7Z4E0lo8IE+3uROzJT5yv/55DAJseRBB0i5BZMgEno KGX/61IiAhq6U9ZwTmrK7xi4EzOepNHFW2d0TpKcZAGtCESQ0uaGIileQTUL4cU4 o0e12Z9ixOXZpJFKigtsVbSe7lrJD9PORQURHGA+p3Tb85VsPwobpNZN8D1sqKif rSunNgh5mLseK5esx2WWen94AlbO4uYViXMK85QIiBkDGdOah5BUD8R0LFnNtPR8 FS+4dSwYJGFCpoYqQu1RoBlIR2hREUmtYFt+8/YBUZOG8Aa4S4R2bt6nc6vP37SE HCbkqJ8+yAmmdL1OXtT8/dQ5l1fnjbOtTAuZcyUMiHZLhRXFkNtUub6Gf+LusZRA Vw2BQTGtqDzbBX7z7gNEPNgcwgI5kwIDAQABo2QwYjAPBgNVHRMBAf8EBTADAQH/ MA8GA1UdDwEB/wQFAwMHBAAwHQYDVR0OBBYEFEssFsYTUSoI/6sRe4KVVdFY50Uo MB8GA1UdIwQYMBaAFCAqCpiHlm6wK32Kv48wTVONvNeTMA0GCSqGSIb3DQEBCwUA A4IBgQBKlh2vXX548odk5k8H+p72VeWatwwcwzdAFKY0KG5kbXGkWeJu8qlioeMl X1tPXB0lRIf9wY+R7/eFLOeUxSqAx8gGMz7hnbG3YhjY71brPqDN8nPQowoxkG1Y 2mCjMGaTAzpO3Bi3MWnf3zrfxxivxuVv6+EyN4YnnQcs9Okd3HxmXmD1cOrWw4KV 11Ucq+Ff4W04Pz7VfftByE0dscD8SXzmnSx3nAMBxWucwXfOsbQRevzCddLBJa/T ySZgvqhMlB7KCfQn/+JsK9N192s6kaq0OtENqEvpi3DrWXydaNCZipMKGoc7gty3 j0sq7aUFfx2ooiDJT+pijT9HJ/N4vLavj8IU06lY1wL1ujKxarME3gqQZNX1iCq/ OL/LAiSRJofvW5GxCB3ALPXhwXmrj6Y7qMvWY5u+cCw/NN3xi4mCOX5Qmk/wbXrC x7j+sza1e3x7CMVmprQYLcqxewaH25APirRtnZdp8doX61fwoh1NU0Y7jehTPbN3 ITy9dIc= -----END CERTIFICATE----- swtpm-0.6.3/tests/data/keyfile.txt000066400000000000000000000000401421141172300171240ustar00rootroot0000000000000012345678901234567890123456789012swtpm-0.6.3/tests/data/keyfile256bit.txt000066400000000000000000000001001421141172300200550ustar00rootroot000000000000001234567890123456789012345678901212345678901234567890123456789012swtpm-0.6.3/tests/data/migkey1/000077500000000000000000000000001421141172300163075ustar00rootroot00000000000000swtpm-0.6.3/tests/data/migkey1/tpm2-volatilestate.bin000066400000000000000000000213321421141172300225420ustar00rootroot00000000000000 "Ú¨mQ”DçãAí6¶ÈuÂQù•fø­ñy8I·€ @”kk¹@½zé%£FXÕ$û¥c¬_o/(¦ŸÀëJý÷øÊ>èZºÍí^ò$\ôngœöœ¶ $ñÛµ˜-O6·•CÐv%Pï“Hýœ«Eú;pDY¯…f–§žÖ¹tr¼¸UX”¡5Šß¼ð…ÁL‰é>®ÝT$Ö8¡Õ¡'ÑÏd4 i<8EBûð•9î·Ç1‹Àñ]ÅÐ0/Æß/6.d¢1°ßZXLƒþ2Ò èhö"`ø&³¸RŠøQ ™nùM‚ª+äÙ+TŸ áNPÈ#v߸$!ZP¢¤<ÏÆ£ð ÿħÞÖ î†æ¢ß Ä]Ô3ð¬ºÂþ“[ç,ý·³¡âï ؄ѩUÑžÜ(‚OÓ_«yÁÃK4¢éÃ"Ì^¢áÿ§ß[”•qXc"Ïé> zCC _»ÐàÜ9.ðzÞ© ÂY°_NÂsx ½Š3æB%*mD=º.f|—À°fýuLM—áGM4ÀÞ!Ðåö– ÙpïÏÝbõ6|f Ñð Û:m0¬ttuí/0ÝCómůÛ!Ù$vRé‡åõrZ‡BÞ²ž(•üªÌû®·ã¨ÀÐ}2Ï/",1\pââ»+4nñ…:2kbמ_ÿlß™•dú)¼)ÑFDµhySiÓIwë<¢ËÝØçË"(–îõ TÔ·î. Ó¢o°ÇÔ©QMôOûõ PXà!Éç¥xí¼è‹ûïžÕXû¨¨xEž¤\w€ç"Ÿœ Ìö¨~×'éþb›'Y)²ŒA!CÈgfÑètXll/÷‰÷­Ù÷,EQ¡‚îQŠØ¨ûIa w=>õö&)l{zŒX„ÃAÝW&²vM–Ú IŸè©ÛÇ;^t—eyg&è‚GÆí£6˜ÂµÖ«S1‰zÞé÷xe»êïZK Zr”࢚Ál&ÍÌß-Ú!Ê4måñZv2Ž•'ôb÷ÐÞ$˜ã UµhS)¶®§ë‚Ñ£Vá%¯›úl-t€³€ÑàlòÀªÊâPý0)&$góæ‹ÐÕ«¸Õfûë~“Ð4°•Vñ±¡ÙÈ%íK7@õÁèÅz}.#Îî1| U>ª&×w§·ßïXfTÎ't^'è1—"E â¯\.Õôé›ÇÝt½;Oµs6uƒò£ß°£æ¾²ñ$Áž YÓ÷£0Ã6F¼ÍSùýEò¼BèâÒh&d¾‡m]ÍîÛª‰ Py5òwvñdj÷Ðm%¸ËkØ“ô²pÑq‹Uïþ¤ª~ûc¡Eü¾ª•G×|ËYž0¥«¯-ÔQNO¶ww^)y`Ù>[…ð‡ ‡¸!oû“ë”71xÿg”0'èfâ‡ìn|(Às˜e‡ô°Òÿ1 †f¤fztõ–yÒZàîHgd&“ ¾Äð¾k·{œz¤ñ3è_ͺhöÒiÐQ(Þ§Mì}¿ òât‚ìÝò6p 3>Žpç‡ `4R# k¦B "GLU]¬ŒÑ‹‚nÎÜÚqŠ*ϧš ëì[ \X@ÿÁDdIÛôçW3x­ 4µ |щC@yÇËž]-yv*#¦[h¹$LÍÓžfà¶@IËY «Ì(áÛ ØñJaL‘"…²cð“f8é ®Ïþ`Òv['äï~€ ¦½l¤7C4 /s±ÅÙQÍö.›9ye-B#z½MÒ›':?FnÿœÝÞMÖ]ì·¡¹ ÄmX¬l¿èkû,Ñþ\/éÝC_z‰iÄ÷£¬1Íe6ˆ‹ï÷_£âj!Î-Bñ7ý¹L¯U°ðÜÌ<Æ„ ´.DaU2¬ûX:§3èëÌÖ¤ëB@ÿ+ß]bÔçDÚúd¶áÈ:¦;uy㓽ÇÚXY:0ø8x:/ËÐÝÈòp*­d}Ð˽Z3I]Š[éÁžCBÅ_*GüIMõºkθi€å·5Ï…V¡%Wï?¤Y L®—ÄÍrpÁº²Nvµ‰6kåe¸5Ò¼4Û•‡žŸ›àüš3$ÅKh­7=i܆1U<¯<üFÖm¬4ÓDçfç"fy¸W™œ4\dË,ñ2åLM[<؉þL8šdIÙ}–n™>- 5 ýõ´(H %¾7°@1Eò•ÆÈrKòÔpx»F!óüÍíöLڢłD®VæÓæ3òzCMÝ‚ü9á ¶V«øÒ›#|3£nìÜÖqnZÈJŸ+}¤>£²Iv#m'Mñ‘xGç×7³ih¿*—èÑ™UJ~±¥Ÿ‚»o½‰xõ#íL§t„l½+>•ÓÇÝ) ß<äsìPö–?KБLŸìúòq´&l©…–áÜ |¶†wZºr²&aö¨¶™¯x²Ýñêqà¦Úu?ƒyû±í¢ f2Q]\£ª[jkúÍ*„ œËEòUòžO2€WY*¤KlÑ[lqKšBú“ɬÜc7¹MèÈ4·BØê¤¯Âôg¬ÉÐ ª-Ý•_ÌCc‚¸ôË_h Õ@[©ÎÉwùˆç+m:5Ô+.§ žB¡ë`U!aß¶Î%o¯bK4‘•Ü„ÖÛбlˆ½ÿLÒ.X×>ð½rúR­K§õ\’õKQ‹t+CîpCœ³ãbBYÄs4„~§BF˜r{’ù„ò3KžÜᄈúkxQl\/?^å+}ò&~µ BŸê¢­XÝË®ã/“r6ôÝÞ‡îË!ÈuÈFƒË-ÁgEˆÁ…|7ù“4k]=¿ôÔRÉ ê ºèÏËÁ]6Ô~_¤&9qúñÜ`¾´ŠyxN`NÜàsæZ`~`¹YFc¨”oða•ý‹…ˆ}zÿÖ»ôRý§µÀ…Û £a^ÃÉi  pvõìžòpN}t©ûWãÌí<„·'/fÙsÛF? ÜY´»|d7HfË—gñ8g@(ˆ^ÜjîˆwKpm5ǹ¥K×çÎa±‚/aðwéç }ßÅ›s“`¼=@T™ŠšŸÕÝ+œ³×¬˜BCŒ>hóÖ÷FÒ•2Õùl¾ˆŒdpf ýç2Ì©tÝÒøusÚÛÉúÞë17m‘!T د/–£7ð™z n@Ft^ y® 6æ–#qy0ù,—š]2‘ î’r[ácËÕ¥š7hg²z •ˆª8®õ4—»µ°<ÜïÖZ —D‘œ <–jÛoOôÒÑkQhk¡Jæ9>è Ýã9pÐ<¨ OYµ‘CÄ @ع‡j˜ ·ÎćÎè6+ª B·á‹£„Ú‘^núÃSά©!ã[´–U«°?Ï`bdSõñ \ÊlpkI›ø;ÙRæN#ÍNNãÁ]A]ªð¬æÜìç!2ˆå"¾ã ™øµRN<ëõ»JÉkù “ üÒм p" ê3ÄF˜€\α84妳êá½ý ËGµB/òÓW¡6(j.R†&V§¯ÐžWGæÊŽï'xAÇÖqã‚ Zç ò<ãÀ·܈Hzê êÿæãCïàF± ¾þÈhßcf i³ ë›}ÛÏãU5 öáÙ‡úò©ÐIÍ}ã? 0V,<Æ=0vî¥e •1<Цˆ«Á< ƒtDå °3›â°ŒÄN­~¼šoâÖ‘9Vj<N†&õ!u~VîG¢Ìät΂ 肹š¨!ÐÿÐK=þñã|ëþø-ަO}•Â4F©Ôk”p -.[,hCe|>$¦ææ™ _Úªñú\]?*º<Ýç÷(²aÙ%±géC£;y Q9¿ 4æpô1œÉÏŸófd†Ï(3Ö,÷.…x$ßÂæÅÌÎöX?·iõYÒbðH›æœ¤Ãôª²ò‰f0½PSJYµ‹ñÇtÒÜ s!¸Ü8xÇÖ¡m*£J³%ºª#<`/" âÊ÷HûéŒñý]Ù,ðG òú—3xy¬¶0Î6ôÊ„WeÕ1šfÄÝN¡œµ·²ËŠk ¶€`±+ÝARKY,ðŽ¡ö_Hk-MN . I|ÑkÙI GnÎ'‡¨ui2ˆá·LRñ».¼)F°sk̢˔¶¹ Â^ï4ŒØe⮯(Yn=‹¾ÝÌë-Ž×ÖbüM'&ÄIˆ±ËÄ $ýtŠçÆT }¹`"nãæd©ÛqŸø¢;ïÆ9õ…NkvÈœWÚC‚ÈÄ­FŠòXÃ<Î.èGl®mé‘ý’> ™ßôÔ*”ÅGIÛ˜‰l•C`ãìñg?ÒªŸ«ß¯f¾¦“1Ñ“g¦½ V}ÅÍxŽ}`¹ÁßËb4cƒ]>D”÷ÒNÎzwª;„z†õÃxNq(#È>+‡e1U^<7øßéŸFB×0xíä§ž01(TG—è*yˆpãƒ&U÷ˆ¾lÇÞ;ó Æ(P´AÉd³ÿ˜¤QÎôCÃÿâÔ\ŸŒ2%ö LŽTW;Pƒýû€¦Çèöãê‚£ŠV®%§ŸÔ5OF‚ŽØ!®+ºÛÎ%H±ñÈiª(>h²„2ZLºYg^jT{—…ÕÉ'ÑN¿ð>xÜwåô½&xØH3_µ&95̽¾­˜£ÔcG"Y"í—æÚä‚2’ßæeg³Çu¯!Ýl¶ ÿ´³Ä è”PyûÖým°ÜMbGÄÏî'/¢7þ0kþ#ú ÉñhòaŸƒ”ž;ÕǾ˜'‹-³{üÒ’x§wŠAéü¿>8h#ì/k¦óYåü’v¹BÌ»‚Lë\ïœUbý¡ªa~.æ«Ø6ó|ô§°ø§ÙGó´ÞŠgÅB1›¤†„×°6j©Žm^,M‡&¨&˜ôNBý%»·üÕôöÞΉʒ ÍÛnëÃOîÅ}É©¬§]Ijã^Þ)Ô¢6ÙSP ,Ë;ç ®Ô^Úà’ë1 [Xn#iú™Í™rèw͇¡Ú(ùo×*R²u·Ñ1evá'sjHÖábÁp÷鬎ËJæM,n¤ãKš¾ö24ŠþÒ«aªU[ñ Ç`l<½öù¯a +gpºàè%S…“ïFYGe¬Ç½¦p> ŽÚñu,è>¦/ç|e‹÷ï‘‚^ô”ÚfÿÖ"¨gd½(~£$ªUQ¼ªì$Ä<ÄâÝ.8P½û¦XÐÛ]¸Ëç`åCŽ÷T|ÖÑU¸†&æÑhÄþ~뺫Ý,h3œ+ó1¡£ØDyŽ«ÞÙÔÕÙ²|Ãë‹UáO7ÆÒibûo¥žš¯…¾‘#jÚ)·N.$_û$O ?šoÄa ƒ>ˆŸÙ#½°ØÕÛ+J˜C7º]7nì•8Àì{EíÅÉ'Œó£Ö¶»JÔ<³Àî§Ø>©v\ oTÈŽàPF½_C…ð%ñ#L@Ìj/²¹Ü4UB•ÃØ{B”܉C÷ñ^‹xSâUÈYþÙDok$u…·_c×8¬ƒ.ç(4v÷wÈ4€:ó >46£Õ!u³^/PÕÑW¥$ËèŠDâË0ÉØZÙ» üŽ p%]Nü ½)+C–µMªñØVD3ý/Ó†D1EiØÍãWðG«äésö‘DbI!ºê8Õ×ì%ßÎÿ7§P™IÄY/ÝØ¤‰/SC9{RÛS=ªu¤ê<É“tˆ\þjr¦âóÌë‰1™ƒël`n%—.s]S ™³)ò‚½­+ÐoJ> „†„3Lx6 wµÕä‹CNçN¶éÊî<puîvj, ãœè_Cj¾Òo‘]lƒAL²ñÅ µÌæhÅ5ðVu€É¦N†d –¨ÁI"î¤Ñ%rxçLÁÔªíØª„¶¿>ë·W{ÆB&•8-=ÎTº!ˆSõ—z+p~Ï>IsŒÚ)nMYôÎvþèXm 2Ñ»úú®”Í5Œ±ƒÈ:`wG'޲(/á…‹嘆f/È‚ "Ñm9•¢§*:.—+ü4”ì{gNA´7U;aJâJ'îE]pzì_œIO¨¹¸Ðéÿ¬–çxÞŒ3`#Yøü ]ƒ¡üž¿3‡ÏRdêu˜•³ŽÌ‚&0Ö…/‡ª¶Kýâj?ï.^3æôc„‚±Õ›Î!BÔò Zm|yÇ;¿Ƥ¬?.î*H9ð•&Eõ¤ˆc…•äqC›ûÈуöÔ¯ ÝÌå‹ÛÁÂd2XæŸò[©½g7èÖîõÜÛb¨ ®d¾‡QÿLë éþ\ŒÆö ¯€Úº—òjBüª?kãAo·éãÍK…s‚Å%U—AÕ ´ !›¼x`KºÂèPu³~{®x,¿¸ )@4S‘2í íí¢ž¨kR_Eã©b”8óæÙKĬHÅØ,œ1f%üœ­¤] o++¤Å*ß%–·Z…œ;ÖtlÖçqßßÜSRKÕA9BV_öô-.³ Ø_xº­¯aCRØïšs5%êÑÙo…ˆU³€¤©Åt— ªyÚºUq8D-ÌPýG¤· àÒó‘ô¬Zx[‚ÓÊòßÊ·¹ýs¥SRËX§OÅ…J!Þ9Ê(%Ãwͦà˜á˜¡>œí̸ܘVf€ ܰZOç]Ï&»y¾:5°ïwù;¨Z£ÛäuJ/;x²Å@ÖõÈÕÌj?àŽ%‘§]¬ŽðÝé„eŽ€çÇ·mHÆ, @툰ð„| ÆW0v+ÚÐrxi'«>÷9ô7`>Ùÿ0)T]â¨h˜ùNéM‡~V¥ý¶\\…ü=Uñœªð¯Qÿp®µSÿ•Õl/¹7Kˆ#¥8áx éÿØâàÞ+ªåTÎM—ÛÄ}ÐtÚÅå[ðÔœ°£¶ìI/ȶöž¤ú©fc=ì?„ ⟢:èÁyÍ÷šÁSç ¸òJ0™Ÿ~Î7ê—­“€?sFI5¿ýDÔféÅð—†L&·Y_Æ« éø7IÚ&¨S=¦(ÐZ$i6ÖJªŸ ¶oۘ̨ªN™Xa9Œ˜aD¹õËt/–ÿ|tLá鳉¸P.„­°bÙÅ Z¸ŠI öðÍ@Žõ’u—7©Š]îý¡4¦˜xø¼M;MSÎLJgSå`¬3â‹%keyearׄŸÕ°ÞˆÔ/}ñ]iœX^¸Ò äs;Ò¾ÞÔ Á>ñ²ÄµÁXgßgQ!®è8²–b ×Ä4j–§z Rwyö"&äo[Ÿrv;ïµb¤]bmšwÊঔÐcûˆ8>׋ÕLÿïvPpléiÚ¿jŸàW¾Ãì#ïxù\è÷ŽHºrŒ¯Öcô,½Ø"Ÿn@·F@^KΗ͛v$.C©·Æ3áúX ·ÐaîÕŽ[ÄN½æìËöJ TªÞÒtÄ)8GáÏž†»jØÿ´¶:{"Ù–t°ý-˜xo1[vÞsID­çñ›Ïöì™—Å–$Ÿt)a“j/¤79fXh>û’È*?¡¦kÜ0n‘õm›S «tæn_»bxsÇWÝdx²&§æàõw–kÒê|Ê“&SØtͽ­ôC#9—§"áÌÐ[vVç✥>Ë~|w¡³¤œœðE07¾;ØŸóA˜UqÒrŒ˜Ê×Ö§aê ‡GHM7 ™ÕCú1»“^ÜÊÖ.…rÞ. wÈßLc¤¬pùeΘ:ú¿AÝxrœèœO-ë j %(!“iƒ±šà:5É“ÒÄå¬eŵ'7®'ÉŠ.FQølUѹ(F¬§“< Ó?K°Qÿ!^(p\õ¯KŸ OųdÂÖ ï|BÅ¿:Øe„¬S9Û2”ÉxØQå˜x/Þ‘$JDç߇µ7{êb”m±íeuõ‚˜™ü€D(ØÓ`ÅœÊo×Ô´9ø¢ßöýªm.]à7‡ÖQ >ò0Ì×hhŸË§²ÏÊM=¤¸*±çµG1ŠÎOw­ ñf„úÔ»²€™áßù=Žæx¬Ç6+aß’æ™Jÿ`pÌ'Éü#j+ø7ª´ŽW×&åýR¬–Cì2yòeðƒ ç’”&‘>&ÚS.1kÕ ÔXèßÁªýÒ* @ðIE|á¾hþ©‚ø´R§ŒS6ToÞ«÷*-ÆÚHõÚ1Un=Üo»‘sÓw\r½_ûÌMÌg¥«]…SJê”ûq,ºYë[/šœž{è›ô[»×à%bú\Ó$¦£bMnÁ6ÂJ󱹬kg"î–`¿YÉ&δ³¶@€ò@ž³XqNKë­ÇLX07’ žÏô{äš/^ ÇOÙr„%<[ï?P «Ñ±¬©ÜE•ÍLt¸ê¨l‡ƒ¿Ò·ü·Z]»—†p¸ô:–B þ÷È)}îr!jñ°ß8lBçJªtXµˆÍâ.’u7úÌSN,î+îaІ¥ï  Ø¥®ÑX¨C¿c\À©-^ofÆ©æâÏ$"& Qõúc‚å› cµ(³0“ÒÛ:‰h§N.‹VKa>¡Q;v¾ŠŒR/ÀÂ%«PÇaä ø ŸìH÷ +&¡>aÏÊoò4˜¹¦í`vãuÎü3„-y&9‘äÃïëÑMC|¹ Î£ ×6fAê¯vtäIKð±âí’Iз@æ»õ]†{FfÇ3”¼ ÒxŮΗӨ¥È©—zjƒt猛ºˆr®å湌QÜî@p¬­”+TçÆãNÚ`úÇþBË07àôaÁ±¿)\ÚÇêO.¾Œ„½«_ýº¹£á©ˆìú bú¢­íLoìd£`<‰#.,f¾õµw?§±HDólÖ¡bY+JÞU©Åõù‡|ë-ÍÑöPû(yïjÍâMp€4»—-íèzTà]àk8`ü$Þ³ h GR–¬LX³þQ‹eí ˆÒêÂö +Ä7$ëêP9¿E7ž39@9ŸŒ]ÉÑs8°7"ÝX&E”Cî=ËÌ½î¦ ¹\Œ7»xîþ'Î<ìeâmP`¡×‚K´,¬¼Ç-ã"U2ÍV,lKu$=jIÞÿy5áá‘Ç´G5©ÌuIMž1à=®tÙ`=S"Fš^žDxµ<¤GõàR©xJã»”VT÷û.MH‰ˆ…•û;*ˆ×ìèe¯j ¦ô1Ä.¨Qº>~¬©¬@}æwA)P°HKùq­T}ÑöÅœ@ZLƒBŽÆE𔯙u戶EǨx›U8¬%¦ñtÓ'ŒÓ¬#[ƒ¤±&§y¶ÀGüeçÓÓâÍ»¹éíjIŒ/`þÙ&9“ŒòÆ«Ë.ïNþ(6Õ•À¢;:ì¶–œh«z÷ÖÍ|°Š^×"ü<¬ð«ºÉÍ“©ÂFm(¿æ  æÖ¨ÒKµÄ¾·ßø /Ï„§—Ð\ʈ„gY$²ÐÚcµ¡ÊBæ¨(<‡HǺ<±î ¯¶c᱕÷þè%ïl… :e‘P(¥Æ5$Ýe:Tøq,É™ÀÕ»\ŽŸÉ_ÎÍO²Z”½"ÃC€+ËJ¹×¤!VÃŽ\yºÚ;±|*ÿ?‰¥Ø;`q!IêO)2 à'B ý­Ál¡(æ›ÿ\Ó¹ÉY 0Apø*WU?ÐÄMv;í×uõýêð¶°rδˊÍ<¦Ÿ¥Ïã‰4å$»„®áXYìk•Ùt|é®þ­0®í·hÇðã_ÍØõæq2qøè¥Œ¢G#ûÖqo•¶„ÙAH=QÄ šPØ(8Mj7ÐêÙ¨NÕE:~Μ§âìivĺã^=aáü/#¨ ,¸¦Ö®øPŽÑI<^`ÖXðǾÓ⻯–Y¨$áMÉ ò݆•òìTxÝg•Üñ«ê—yzmzþÅÐf¶\@­ìå;@L’=D—s-ú[Hõ‰ KhQcë$¡Ø. eÌóðð‘’+¹^èð‘¥—à˜å!Ÿ´¯aušoõÙÄ]·¢Û)vÕs1IíI$.ÑÚ%œ¾ñ«z1ɸˆì ¡Ëpç!= ~æ4Öñ¯÷ÀÊØÃÑ~òyÇ œ«çÐ «5qà^£swtpm-0.6.3/tests/data/migkey1/volatilestate.bin000066400000000000000000000024121421141172300216600ustar00rootroot00000000000000  dŸ¨™½€MQÝsZ¡²wà_â~nå8 ¯Æºuà'Äc·MU«áEŽlßµœK¦ @„Å¢y0:É×Åí;[Ÿ7ë~ ÈdåÊpn®¡WV@2°w”LŠ݆ð˜Û_ˆÝ§âÔ®,ó¬uQGó;¯ŒUD¸ùêÃþHð1ý –׌¢µMYHQþ–· >>ŧŽ*Ém)˜žÿ¾‰õ¬sA7FǰwÁÿgÂKSäã¨MªÑñ$¯ÏŒüZ¯èhã¦Þ” <«ß;}¦ïŸØ×´•ÈÓ­WI+¢Kvü†Ye7 bp¥›QÛØÇEÐe¦_eùh›°Ü¨E®ŸR÷ÇO¼Pˆùãi‘´Ô"Âp*Qæmx኿š+ÖÝß JÒø2«ÕÖµFY‹˜î:Ðð×h’ÕñmÝšMµî†wÓšP2AìØÅ êZuÉþ1 s‹ÇÆèE‹AÅk…¢õóg€Ù3h‚-~.¨§PÚ¸Ôz§ÙýѼM¹xÝH’4õZÜ…‚+!y ÈùÖYáþcHkOeõ™ /OI~X¶î]Ž”}à >$!ʣMJF5búêg‹9í‡6LÈÿÞ¾ÏÒk€‡ÜLФ1œpN~ß‘ VI V…Í~$&¢ÌTmHóžû‰3µ!Üž™e7ý>›Èá+Ü×ÔÕØÃ>ÂÖÓcNY Ž}· ¤®9¹¹ÿ$¸áZóMw$Q~[q]ô5˜ªˆý!|Ùc*Bx©=„Z?²B£f+œÏŠþ/ Eï‚ä¦+ÛG'ÙbÃö½apVVLÔk×#~$ûÌ»:H_¸/ ÛÞWM…—|KڗØ?kJyór|ˆ433j»RÇÚ¡EcUjìŽ\i›u™ÿѰÖöÝáüVõµA1«ŠZuKŽ<*OÐ7>“Û}º9Þeǵhwh솒œv^æg2¤˜ºØ¦[~Hök ¾ŽßöDK§>e¬€[¦UBôœƒnß“?a®‘Oòï«%¿Ãn/À“òìÕJáqBѬ؇Ù×úC ,L刕Žÿt Bï~Óy‡Ù‡n;´F=øÎ_rÒcxÝ;"¥Æ»Vº”Æ& hƦNCÑo×Úg9(‹ú¢a|(˜ëjË}c)« Ù`nô{‘È¢]™:apn*‘UýÓlH9b ù+9P>¸â–1ùMßPc W=|”N8BΘâ1ÌÄÜ*'-÷Èjg/ˆ ̆ô¨ë¿Ï" ,—f¦Ý‚;ΰ—C2¸ò‚Ý:/T$H§’cŸ½– 7ySÐ=cŠ‘&íŒ p<öB´ÄÅÜláu+v¢k<¶ð‹YûW}ĦfϾ vǪ”™H“rv`*eÆOšO_¥‹×»;š…&¬ `Zb -"©§¦ «ˆ”´a-ñ{JˆÃ'Çó .Ì|mg=‰å€ò½> \;܇yõ5üÿ£5nY ?¨¾û¥ÌåÍí0'‘õ+ê\ÊLj8.kÝ’¯{ƒÁ˜-Öøµ¹f$Ĉÿ­„èW(ëjé&m1sgœŽº©”˜³€ÐÞ¼mœàW@$¸þà*TK|­­· y äW†ž(;eLm¾iîGö×SiÛ*$Q ÚÉPÞø9^*è®Uuìé4«>%QQžÎ:,d„ܶswtpm-0.6.3/tests/data/pubek.pem000066400000000000000000000010041421141172300165450ustar00rootroot00000000000000-----BEGIN PUBLIC KEY----- MIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEAv1muaCRQNM6UweD+Bpcl q7Pbysd+RrpugzdPXA+lVY8yPwKSvX7jjW2fVp6SpUnqupxiqjZIWaQPznjtlHRi 7Ak8cl+pBLoBLYfEpz+EUl+IFTOaRSV6tN3ljTEh/gNhgzVk9mYB+4kgfZLNPezc U4YRypCWxg8ipjc97Pv4zqnRaWCL7mfdmdzoddyjOx6ekvZvg8FonLW/qPOODGyR qwN5chRD8VzRQBo0xDtPJ5Sph942/Xv5PI34P+wO2aGFzLsLD1IuEzNDtu19zEYG HqxLuZn0YHp8ouTNKRiQRnfyHE0tLDXiAbQF71wjFQMxXXK3+DC1C0LC0Pub0sir oxFB4hBG2tuSiM45zRj4M0J8JAfA6d6ef5bygFJly5ew9xXQc0do+1hVtROUyUSF PwIDAQAB -----END PUBLIC KEY----- swtpm-0.6.3/tests/data/pwdfile.txt000066400000000000000000000000121421141172300171250ustar00rootroot00000000000000mypasswordswtpm-0.6.3/tests/data/signkey-encrypted.pem000066400000000000000000000047621421141172300211210ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,4F72E2939BD5ADD1C5F148D23C8C7B69 7ROHqAz7swVFcJCsxSL1TEYAWNB/WLFq7MM1pAT0CiWsm4GODgERLHb1/Zm9I8s4 gvpAkpOslbjBZKP+kz0DgwR30RDiMalVniWrCYJn91gIqcRCjKdk400ktzg38Nr5 yEIMODGDskumbxXV6vaFTh6blSLHfLmo1WNyKGeHB8MX2+oQUpZKL31JNWorMRHQ gF32UOcsLFR1ZAgjtxjeFiYremmxDlBIl2OrIrl0ZepFtbLIxV8Gqpl342rN1fBo Clks/3DHzbLjgHh/LozArdhqZFS7axp2N3V/W3TtrrLcY5sJXTFDZ+y6Dv4gREq+ 9HwwvhvjlxNovvbM4JQigf7G5C7EGRvoLJYgrWi6nB34l/mX86Us3LD+dSmTVUM/ sqy7hnXYpZ2Xyj3UaL7pXwqlhx5dqrpBf2cr+jIhcXkCRE4Sxo438kvd91rLZyFG 3/28x36MIFLS0yJscXHx58j55pEtBeGA+WmMSuWIFdk9dhp0Ntb4nskaOGyKzITk mspagdstrVAd4EWpaeL8MsGE1vVXWKC2fJrt8UlZPy0C7AlbS53SSAdrddxCOFN6 LMGzZl73Szy+FRADuL0jJBYnJm84DBx5VXHx9jjRVKlfMUy7Rg/QZvHqC0cyEd/b ccCMXeGqLGrVxj5uXZ/aHb0E3e2TU1PgZBZTU9RXfDmQUy2sxzlFFbfpeae9KOB+ vu/v4sjbsZatFgHUwB7RZjosgC+b6eWJlRtkR2qC1S79Hjpa1P8VMHgR8G2Uyg43 j4101PgA/dbOpFXQ2e4MX7vs/nuGEgd2+JNRnIQ3g5lnWzHBCjGtRsAmsYxTZjZc CvuaGStwDk4TZbJqI4jQmcgZ1dKpXT+ElFyfWzrufYIZL5QyyazUtz1EOqPR+rdl 9NZ6gI9SSKhobqHPY5nffMq2hCOjkYJ0gKp9ufiQKLS2U3uzqNJ+ZINI7lzjj2v1 Y96Frn8RVF/7Vks+FVlurpM9110toPfNNrqph+KDQjIotIdfGAUJOyypBA7aTD1q dz6M6SVOAyVhtnx1LqA5kR3S/yjFipVOT0XZli04gCEKsAOPGsVp7v0+Bij3x1I0 WK5shQsZzUaiHtDxdQl0yoVmC6ujjHWpGOPTq+qWkd5dtlxNpPTOKXhAQiyRGV3D ytHCjxV+5obqpwdYK7s/+eDtlbLum6zBXY7OU6TwJJB3wdteYpi/mGVWDxiBqCVa iQnG7ulr+nBNti1gGj8NwtQ1mCPZsuLkrqwq8hrDOJan8JQC+xUz/DGdsUKIFlYn WeamZ94kQSCNLmmS0eEac1Npq4b7z09y8zZ8lb6hAGe1LnVa+Jsumj4r7Rz1XMMe pj4nc1W2BwNzjgNo92JkkxCFEwDH+HOceh8S9yRPOQYzvvom8jCIgdU5f0aNgxQw HdPTjYRMHoXe0rxovMFS2xhxOJd80JiNhaiZo57CqES4+LRe7jgZHc+LEQEn4pzY 8bTWjyk5yZkpDvqrYTTsl5w2v83YAiRibAvfpilfkgzrjK+IQB0OAS77X/TcFHho bfwfeb6WWSpl1ORLm0exUXu+Gbe5n5axCNVtwyrVD+nTevozS/manKHLrsymJ628 Bej6lZmr5fISn5y3xRaW4ktRrdeibpOGVOELBMsU7icm2DzJFs/JpCMJElV/qNsD KcBDOhRkt3qnQuCXk+bRdlNUpEFXzHP6oD9j1/ueA5sFG1m4yAHA+y16xCussdTJ mC9JtCt10cXnqHULBfrTxu23a4E+qEa1GKKbV/vnJGlqPhGkMZeuuXz8gEoAyC5S Xf4XjFXAY9CBLbzD43TCIdUTYrpq22XMbICC2dmD9UF9+u54VQnIolxvgqRZEe/b Kpur0RTyWci8xXpKM0gzVi1JNyb6QijvEXif9JhW+a5PaKT5SZwB36Rs0uT7ZYl/ h+Jc+ylh4ITxHYNkZxjTgXN1kxcKgq5A0ojvxbDAe40ZY06TqiOfmI/CQE8f6vkp 4/oeq+9HHAs7uiu+KEkDpBnSopPKRy9UBC0UZVkq7AUpeRAEUnUbkOI91afKbkms 0yNcVKkNR/Hx9IK32A0vr9cZoJshG4GA63I2i/HO0F7cJAtHM9A6UGH7/PaM7OSZ 6m6q3hv/nIfTrMkPaIhVnOjNJehlnbb6IIICs1Wrs4GFnOiURFW4AjRRjQagJF/x u6Lzx3AHepYdYhBISyM5PuxP1FUxYjxkI8tUT78F0vbYo+xfQ8JTX/wRT23T3Tnj yYX/R9h8Aqb3lRSpS0IyAHuuO79c9ih2D0uF9WaZBfwZD7x/y8cpQV07gXMhkHb6 uPpjKpnDY0yvS9qNSCJJ32oBUQCpvSpW2qK5AiDwfDcsP8e+kAsew8/V4GnRuqFp -----END RSA PRIVATE KEY----- swtpm-0.6.3/tests/data/signkey.pem000066400000000000000000000201411421141172300171130ustar00rootroot00000000000000Public Key Info: Public Key Algorithm: RSA Key Security Level: High (3072 bits) modulus: 00:bf:b5:b8:14:d0:e7:25:4e:cc:0c:24:80:d5:b1:45 bb:2a:28:b3:2f:c4:f7:11:71:ff:16:4b:bd:19:48:e5 2e:f6:7b:c4:2c:3b:cc:40:f1:06:13:b6:38:f1:0c:6f d8:ef:d7:67:c3:da:f4:7e:86:ba:98:3e:ba:f5:01:4d 89:e7:1c:15:20:24:bb:97:17:d6:03:9d:a5:da:4b:52 98:d5:d1:ce:54:e6:50:ca:01:72:4a:ae:d9:e0:4d:25 a3:c2:04:fb:7b:91:3b:32:53:e7:2b:ff:e7:90:c0:26 c7:91:04:1d:22:e4:16:4c:80:49:e8:28:65:ff:eb:52 22:02:1a:ba:53:d6:70:4e:6a:ca:ef:18:b8:13:33:9e a4:d1:c5:5b:67:74:4e:92:9c:64:01:ad:08:44:90:d2 e6:86:22:29:5e:41:35:0b:e1:c5:38:a3:47:b5:d9:9f 62:c4:e5:d9:a4:91:4a:8a:0b:6c:55:b4:9e:ee:5a:c9 0f:d3:ce:45:05:11:1c:60:3e:a7:74:db:f3:95:6c:3f 0a:1b:a4:d6:4d:f0:3d:6c:a8:a8:9f:ad:2b:a7:36:08 79:98:bb:1e:2b:97:ac:c7:65:96:7a:7f:78:02:56:ce e2:e6:15:89:73:0a:f3:94:08:88:19:03:19:d3:9a:87 90:54:0f:c4:74:2c:59:cd:b4:f4:7c:15:2f:b8:75:2c 18:24:61:42:a6:86:2a:42:ed:51:a0:19:48:47:68:51 11:49:ad:60:5b:7e:f3:f6:01:51:93:86:f0:06:b8:4b 84:76:6e:de:a7:73:ab:cf:df:b4:84:1c:26:e4:a8:9f 3e:c8:09:a6:74:bd:4e:5e:d4:fc:fd:d4:39:97:57:e7 8d:b3:ad:4c:0b:99:73:25:0c:88:76:4b:85:15:c5:90 db:54:b9:be:86:7f:e2:ee:b1:94:40:57:0d:81:41:31 ad:a8:3c:db:05:7e:f3:ee:03:44:3c:d8:1c:c2:02:39 93: public exponent: 01:00:01: private exponent: 00:be:f0:c5:29:a6:6f:b2:4e:eb:18:64:fb:14:db:7d 72:4f:29:3e:5f:23:b4:58:e1:cb:89:6f:62:26:5e:de 35:8a:35:f7:4b:7f:3b:8e:ab:00:bc:7d:4f:f5:75:c7 a8:b0:29:41:26:67:5c:00:f1:3b:c4:0b:26:b6:83:d7 b0:b4:48:da:19:ab:bc:53:5e:e0:3f:b5:b2:cc:db:1c a7:30:bf:c8:db:f2:91:20:c1:94:0e:22:5c:ca:f4:cb ba:70:b1:f9:b0:37:14:58:aa:0c:a3:5c:3c:4d:85:b4 9a:2c:2b:86:c1:8b:9f:52:0e:ac:8d:d8:3e:cf:48:98 03:5b:49:37:af:ec:f2:ea:87:9f:1b:c8:e8:fd:e6:f9 e9:7b:2d:30:3e:b8:2e:d2:03:85:ef:cd:61:60:b9:45 f5:68:3f:7a:28:70:95:df:01:bd:27:0e:29:8c:4b:f6 5d:af:72:a6:f5:2b:e8:ab:d9:78:cb:5c:1c:b7:96:20 8e:30:bc:ba:0c:7d:66:fa:11:0a:d0:3e:02:b8:6e:64 2c:73:4c:cc:e3:f0:6a:8f:7c:a6:a2:17:6c:d2:82:47 17:33:e3:17:e7:a4:ad:e0:5c:d7:23:50:45:f2:fc:a8 47:9f:c9:26:f9:9b:e1:94:4d:cf:a5:b5:bf:96:9a:80 e9:39:8b:51:5e:79:59:85:c1:fc:25:96:9e:4a:ce:b8 b9:48:ed:cc:b9:1a:a1:98:05:7c:02:6e:53:39:b2:eb 48:14:89:0b:60:2e:ea:64:89:05:11:e5:39:b0:72:0f a3:56:bd:49:65:eb:d1:51:30:a2:c9:d1:f3:f2:e5:4b d0:f6:ff:e4:8d:87:bc:24:a0:6b:e2:7b:c7:88:26:c6 2a:f0:3a:94:a9:4a:cd:04:f4:9b:e1:78:f1:94:ff:11 31:80:5f:be:05:8d:f0:16:c1:0b:61:02:2b:cc:6b:7d 01:c7:2e:2b:dc:e0:9a:07:67:1f:db:a8:d3:f5:65:3e c1: prime1: 00:c5:1a:78:1b:df:1d:ec:13:ac:52:53:85:b9:63:c8 dd:5d:05:83:34:3e:07:b3:d4:2f:75:5d:a9:28:c3:96 84:18:31:ac:c6:d4:81:23:c8:67:72:e0:44:97:92:36 5f:0a:30:ed:d8:75:7a:46:ed:83:f0:6a:88:bc:fe:0c f2:9c:09:3c:66:01:71:ee:4c:5c:5c:6d:6b:97:56:cb 7d:2c:90:ce:7d:b3:e3:94:3a:27:94:40:1c:aa:8a:ae e1:b9:d8:0d:5a:29:a0:2a:54:bf:77:23:22:58:8c:29 3a:ee:15:d5:57:be:41:76:78:c7:11:f6:6f:8d:80:89 1e:1a:d7:a4:a5:a5:df:cf:81:00:bd:fb:de:f3:cd:d1 5a:76:0a:52:ed:68:ed:7e:ad:16:96:df:95:8a:59:25 33:2d:35:0c:e8:02:19:96:be:40:a7:91:08:a2:16:01 05:6b:12:04:e7:91:41:39:1a:a9:15:21:e7:d7:59:f7 43: prime2: 00:f8:fe:aa:bf:03:5f:45:c9:7e:7b:ac:d6:28:55:70 59:f1:68:0c:56:89:2b:38:2d:98:41:63:11:98:f8:7d 8b:e1:76:58:0e:17:e2:d2:0b:fc:ee:31:c4:27:a3:49 28:5c:2f:21:1c:75:89:6d:6c:b3:ce:d7:50:01:a6:ef cd:ec:e8:1c:01:cb:86:42:66:65:f8:c1:30:44:5d:6f 9c:51:8b:33:a1:e0:d0:dd:77:f3:6a:05:37:08:87:ad 3b:de:9c:d3:45:60:ac:d5:59:0f:09:53:ff:eb:eb:94 22:a6:2c:f0:0a:a3:82:c9:67:9a:28:73:8d:3b:36:3d e7:1f:7a:1c:0c:86:04:0f:f9:14:b3:f7:88:88:94:30 38:28:45:96:a7:8b:a2:96:3b:4c:0a:9f:53:15:5a:ef 92:97:e2:73:2d:49:f8:ab:b1:e6:81:12:36:0a:e6:a9 18:3b:99:48:1b:8a:ca:93:55:16:eb:97:fe:60:9d:c7 71: coefficient: 77:f0:e7:18:46:f3:f8:b6:01:33:c4:b1:15:8d:ce:dc c7:ee:c1:45:96:66:7b:13:6c:2d:fa:dc:f7:53:98:af 45:4f:f6:a0:48:9c:34:31:9a:cb:24:f3:24:52:83:e5 ad:14:15:75:13:6c:15:37:7b:18:af:39:e7:35:91:3d 9a:c3:64:51:fd:95:48:7c:18:68:7e:2a:0d:f1:92:f1 fa:b0:a6:b0:71:b3:71:1d:c8:19:24:05:f5:99:2a:a6 47:72:e7:78:d3:48:80:03:5b:a6:2e:ac:6e:6d:d2:e6 fa:2a:e4:70:84:1c:bc:46:58:5a:9c:b9:da:c0:eb:63 99:53:86:8f:1c:23:b1:20:c8:10:dd:2f:15:12:80:ad 67:dc:1c:29:60:bf:68:c7:ff:e2:98:38:eb:e9:22:3d 47:63:8a:2b:6c:70:a8:4c:b4:8a:2e:ac:3b:9c:49:fb 30:14:38:0e:de:eb:67:b0:ea:3c:72:f6:db:36:45:86 exp1: 00:91:ed:73:e9:66:ba:17:93:c5:2c:3a:8c:31:e2:af cf:3c:54:9d:7c:2b:44:b6:9e:2c:f8:de:fc:23:a3:13 27:ff:65:9f:be:a1:8c:6e:fa:ab:a4:80:68:28:33:e7 2f:5c:33:37:94:df:fd:44:d0:0a:b4:0f:9b:e7:18:cc 6b:3e:9d:13:eb:8d:bc:55:2a:91:e3:18:5b:e4:f3:2c bb:23:28:9e:c8:b0:4b:98:ed:a9:69:f8:41:80:fe:26 56:16:aa:df:cf:d6:2b:af:cb:88:e9:e2:c8:45:f8:97 79:fa:d5:8d:5b:66:0f:bf:6f:d2:2a:f9:62:43:c8:5b 3c:3f:b1:52:44:15:d7:eb:20:5e:75:4a:2a:1a:25:52 8f:7f:ff:4a:c0:5c:c4:20:da:73:74:06:5b:07:cf:d2 5b:de:67:7d:83:b4:32:4f:c9:d1:c2:7d:fd:7f:4b:7d 3c:0e:b6:8b:8d:0a:9c:d8:73:65:a5:b0:b1:9e:5e:0c 53: exp2: 6a:83:6e:81:45:ad:04:ca:7c:2b:e5:b4:bb:0e:49:80 80:4f:55:2f:d3:7f:c4:89:64:9f:5c:04:d4:1e:40:7e 8d:15:35:f7:d9:69:f3:16:a3:bd:35:56:c6:ea:07:ca 97:1c:a6:1a:69:81:3f:69:07:c6:0c:bf:31:e5:ba:a1 a9:9d:65:15:b3:7d:9c:7b:f7:55:21:37:47:97:7c:be 2e:f7:d0:3f:88:4f:70:dd:f6:27:bd:51:5c:79:c5:b6 5d:b5:52:7f:54:2a:bb:1d:5c:dc:4d:ad:a5:bb:61:e4 2c:97:fe:9b:5e:74:fd:39:2f:6d:ec:78:57:03:0e:1a 07:92:11:db:9d:9c:b1:44:89:01:af:7b:1d:89:de:d2 b7:0f:85:b1:e8:7e:c5:ab:5a:0d:15:38:d2:62:d3:27 2f:87:f4:63:44:48:77:12:24:1b:c4:b1:8f:9a:3a:6d 9e:59:24:ca:7b:65:ca:fe:d4:4e:35:f7:e0:56:be:51 Public Key ID: 4B:2C:16:C6:13:51:2A:08:FF:AB:11:7B:82:95:55:D1:58:E7:45:28 Public key's random art: +--[ RSA 3072]----+ |. =Bo .oo | | o . o.oEo.. | | o o * .. | | + o + | | + . o S | | o o o o . | |. + o . | | = | | . | +-----------------+ -----BEGIN RSA PRIVATE KEY----- MIIG5AIBAAKCAYEAv7W4FNDnJU7MDCSA1bFFuyoosy/E9xFx/xZLvRlI5S72e8Qs O8xA8QYTtjjxDG/Y79dnw9r0foa6mD669QFNieccFSAku5cX1gOdpdpLUpjV0c5U 5lDKAXJKrtngTSWjwgT7e5E7MlPnK//nkMAmx5EEHSLkFkyASegoZf/rUiICGrpT 1nBOasrvGLgTM56k0cVbZ3ROkpxkAa0IRJDS5oYiKV5BNQvhxTijR7XZn2LE5dmk kUqKC2xVtJ7uWskP085FBREcYD6ndNvzlWw/Chuk1k3wPWyoqJ+tK6c2CHmYux4r l6zHZZZ6f3gCVs7i5hWJcwrzlAiIGQMZ05qHkFQPxHQsWc209HwVL7h1LBgkYUKm hipC7VGgGUhHaFERSa1gW37z9gFRk4bwBrhLhHZu3qdzq8/ftIQcJuSonz7ICaZ0 vU5e1Pz91DmXV+eNs61MC5lzJQyIdkuFFcWQ21S5voZ/4u6xlEBXDYFBMa2oPNsF fvPuA0Q82BzCAjmTAgMBAAECggGBAL7wxSmmb7JO6xhk+xTbfXJPKT5fI7RY4cuJ b2ImXt41ijX3S387jqsAvH1P9XXHqLApQSZnXADxO8QLJraD17C0SNoZq7xTXuA/ tbLM2xynML/I2/KRIMGUDiJcyvTLunCx+bA3FFiqDKNcPE2FtJosK4bBi59SDqyN 2D7PSJgDW0k3r+zy6oefG8jo/eb56XstMD64LtIDhe/NYWC5RfVoP3oocJXfAb0n DimMS/Zdr3Km9Svoq9l4y1wct5YgjjC8ugx9ZvoRCtA+ArhuZCxzTMzj8GqPfKai F2zSgkcXM+MX56St4FzXI1BF8vyoR5/JJvmb4ZRNz6W1v5aagOk5i1FeeVmFwfwl lp5Kzri5SO3MuRqhmAV8Am5TObLrSBSJC2Au6mSJBRHlObByD6NWvUll69FRMKLJ 0fPy5UvQ9v/kjYe8JKBr4nvHiCbGKvA6lKlKzQT0m+F48ZT/ETGAX74FjfAWwQth AivMa30Bxy4r3OCaB2cf26jT9WU+wQKBwQDFGngb3x3sE6xSU4W5Y8jdXQWDND4H s9QvdV2pKMOWhBgxrMbUgSPIZ3LgRJeSNl8KMO3YdXpG7YPwaoi8/gzynAk8ZgFx 7kxcXG1rl1bLfSyQzn2z45Q6J5RAHKqKruG52A1aKaAqVL93IyJYjCk67hXVV75B dnjHEfZvjYCJHhrXpKWl38+BAL373vPN0Vp2ClLtaO1+rRaW35WKWSUzLTUM6AIZ lr5Ap5EIohYBBWsSBOeRQTkaqRUh59dZ90MCgcEA+P6qvwNfRcl+e6zWKFVwWfFo DFaJKzgtmEFjEZj4fYvhdlgOF+LSC/zuMcQno0koXC8hHHWJbWyzztdQAabvzezo HAHLhkJmZfjBMERdb5xRizOh4NDdd/NqBTcIh6073pzTRWCs1VkPCVP/6+uUIqYs 8AqjgslnmihzjTs2PecfehwMhgQP+RSz94iIlDA4KEWWp4uiljtMCp9TFVrvkpfi cy1J+Kux5oESNgrmqRg7mUgbisqTVRbrl/5gncdxAoHBAJHtc+lmuheTxSw6jDHi r888VJ18K0S2niz43vwjoxMn/2WfvqGMbvqrpIBoKDPnL1wzN5Tf/UTQCrQPm+cY zGs+nRPrjbxVKpHjGFvk8yy7IyieyLBLmO2pafhBgP4mVhaq38/WK6/LiOniyEX4 l3n61Y1bZg+/b9Iq+WJDyFs8P7FSRBXX6yBedUoqGiVSj3//SsBcxCDac3QGWwfP 0lveZ32DtDJPydHCff1/S308DraLjQqc2HNlpbCxnl4MUwKBwGqDboFFrQTKfCvl tLsOSYCAT1Uv03/EiWSfXATUHkB+jRU199lp8xajvTVWxuoHypccphppgT9pB8YM vzHluqGpnWUVs32ce/dVITdHl3y+LvfQP4hPcN32J71RXHnFtl21Un9UKrsdXNxN raW7YeQsl/6bXnT9OS9t7HhXAw4aB5IR252csUSJAa97HYne0rcPhbHofsWrWg0V ONJi0ycvh/RjREh3EiQbxLGPmjptnlkkyntlyv7UTjX34Fa+UQKBwHfw5xhG8/i2 ATPEsRWNztzH7sFFlmZ7E2wt+tz3U5ivRU/2oEicNDGayyTzJFKD5a0UFXUTbBU3 exivOec1kT2aw2RR/ZVIfBhofioN8ZLx+rCmsHGzcR3IGSQF9Zkqpkdy53jTSIAD W6YurG5t0ub6KuRwhBy8RlhanLnawOtjmVOGjxwjsSDIEN0vFRKArWfcHClgv2jH /+KYOOvpIj1HY4orbHCoTLSKLqw7nEn7MBQ4Dt7rZ7DqPHL22zZFhg== -----END RSA PRIVATE KEY----- swtpm-0.6.3/tests/data/swtpm-localca-rootca-cert.pem000066400000000000000000000026601421141172300224360ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIEBzCCAm+gAwIBAgIMWtYHsQCZEuhkMw24MA0GCSqGSIb3DQEBCwUAMB8xHTAb BgNVBAMTFHN3dHBtLWxvY2FsY2Etcm9vdGNhMB4XDTE4MDQxNzE0NDE1M1oXDTI4 MDQxNDE0NDE1M1owHzEdMBsGA1UEAxMUc3d0cG0tbG9jYWxjYS1yb290Y2EwggGi MA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCr+QDbyew2WXnlSyPiTDaRHlFz u/YxVXgpHUf1OQjnxg3rsYq87TBa058R5DkqdJwtwIzHL4zlXrK/fq2LDFTeS89v QSWMx61SayExCCKOQqkTs7jpt8Gy1PNxVeCekyXKwevwRAt0dVebLANwy1xaOlyQ XpSyCUuJIn1jrmCJIP7yK8EJnOSXuMrH4FZbRC2OkQXmS5AETigZ9lpTxuB2bukp egf5dNVW3TBW/ugH9/wToSvkisrchv/IHxqGY7tAADo8a31ptJ1uURbeY1tHQtwd qBuj9t3dWfmzSdC4RTyGzwywTrIgT/xn2bagVCMNzxiAjHthmotNZ7XjNlO6IZMJ DBJXmk8H8Nf4I8HTNAPRfXYUkVmHx82909PnpC9UV0z/m7v2JSUKvQYHSes+Kan3 n/Rie7/fOUUGuPhozup5gTauPgVue8YtYGY0DNeLwK5BrImRM9apDuUJQ8LSLa6c d45SzPp16+GJ6qCKQTEnSdmTyeg1k+L61h+EN80CAwEAAaNDMEEwDwYDVR0TAQH/ BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBQgKgqYh5ZusCt9ir+P ME1TjbzXkzANBgkqhkiG9w0BAQsFAAOCAYEAi4Ed2INpqVXvZkoJ/771U+jBS2PQ IP+2OynmMd0OLFMwcKMds38joRR+K9IVS0z3gFI9uH0hMBtozLI809qTGBV2CLsP KS0MMSIjtFzxGRKeHqRO8Iys3Z5kxc5dPUP+d9nODDhrUpGTFBuplhD6PpypOrfd wYgLNhtwcqZ5hVdK/QZ8Ti4ZlrpeMCRMPs6ZVJU/d3YDFZNygCKnDhAlcf+06UG+ LeqF64FhyokSyn0nflzSziuAmQhiBdY/l6XuOLbK9K9VBVVO1RtfHderc/lvqCs/ 0rmgjPLNfo4nLJNz8gk0SsHmF8ntKx8hcKeepnAFzlM/XvL6faJXXm5axmMNd+kb Vorqs23oHaqgY0Z9XMm2NjBo3DnkANUDywYVddhcqa+VABl8KjZfal9mIzNT+wY2 jbFFbRwwkox7+UaZuFdUoxWd4zQEed5pcNeBbrFUrFeLln7Dsn0npYc7UlJpwI7W +181x87URGPZcu/ykj6XD0wsxonAjXZIIwIb -----END CERTIFICATE----- swtpm-0.6.3/tests/data/swtpm-localca-rootca-privkey.pem000066400000000000000000000201271421141172300231700ustar00rootroot00000000000000Public Key Info: Public Key Algorithm: RSA Key Security Level: High (3072 bits) modulus: 00:ab:f9:00:db:c9:ec:36:59:79:e5:4b:23:e2:4c:36 91:1e:51:73:bb:f6:31:55:78:29:1d:47:f5:39:08:e7 c6:0d:eb:b1:8a:bc:ed:30:5a:d3:9f:11:e4:39:2a:74 9c:2d:c0:8c:c7:2f:8c:e5:5e:b2:bf:7e:ad:8b:0c:54 de:4b:cf:6f:41:25:8c:c7:ad:52:6b:21:31:08:22:8e 42:a9:13:b3:b8:e9:b7:c1:b2:d4:f3:71:55:e0:9e:93 25:ca:c1:eb:f0:44:0b:74:75:57:9b:2c:03:70:cb:5c 5a:3a:5c:90:5e:94:b2:09:4b:89:22:7d:63:ae:60:89 20:fe:f2:2b:c1:09:9c:e4:97:b8:ca:c7:e0:56:5b:44 2d:8e:91:05:e6:4b:90:04:4e:28:19:f6:5a:53:c6:e0 76:6e:e9:29:7a:07:f9:74:d5:56:dd:30:56:fe:e8:07 f7:fc:13:a1:2b:e4:8a:ca:dc:86:ff:c8:1f:1a:86:63 bb:40:00:3a:3c:6b:7d:69:b4:9d:6e:51:16:de:63:5b 47:42:dc:1d:a8:1b:a3:f6:dd:dd:59:f9:b3:49:d0:b8 45:3c:86:cf:0c:b0:4e:b2:20:4f:fc:67:d9:b6:a0:54 23:0d:cf:18:80:8c:7b:61:9a:8b:4d:67:b5:e3:36:53 ba:21:93:09:0c:12:57:9a:4f:07:f0:d7:f8:23:c1:d3 34:03:d1:7d:76:14:91:59:87:c7:cd:bd:d3:d3:e7:a4 2f:54:57:4c:ff:9b:bb:f6:25:25:0a:bd:06:07:49:eb 3e:29:a9:f7:9f:f4:62:7b:bf:df:39:45:06:b8:f8:68 ce:ea:79:81:36:ae:3e:05:6e:7b:c6:2d:60:66:34:0c d7:8b:c0:ae:41:ac:89:91:33:d6:a9:0e:e5:09:43:c2 d2:2d:ae:9c:77:8e:52:cc:fa:75:eb:e1:89:ea:a0:8a 41:31:27:49:d9:93:c9:e8:35:93:e2:fa:d6:1f:84:37 cd: public exponent: 01:00:01: private exponent: 49:ec:c4:1d:b6:f3:3f:79:bf:18:7d:f0:72:fa:e8:0a 01:ca:69:c1:c6:d6:f6:32:ad:19:d5:30:e8:cf:97:32 60:11:8d:44:62:6a:63:7a:e7:b5:5d:6f:89:d3:62:45 30:b5:b0:ce:7e:f6:46:33:2b:0b:7e:5d:03:84:cd:86 b1:77:fe:0f:37:21:09:44:cc:45:19:03:86:c7:b3:f7 9b:ce:c8:57:18:c0:d1:17:1a:cb:7b:50:bb:39:ef:6f 33:75:a1:02:ab:7d:71:16:70:0e:58:21:32:7f:78:b7 a0:96:e1:c8:86:8a:f1:cb:f2:ab:4c:d3:68:c6:3e:ac 5c:6b:a5:bb:59:72:84:21:64:62:67:01:5c:9d:e6:f4 de:70:20:e5:1a:5e:52:3b:76:a9:92:68:c9:d2:97:f2 d1:42:91:7d:cf:a7:c0:3d:65:15:b8:0d:ed:8d:b8:bf 35:31:0a:fb:5f:46:fa:65:49:f2:f2:07:cc:d3:30:53 3d:50:c6:40:93:32:04:ee:e5:a4:32:1b:07:0c:d1:87 bd:49:cd:0f:c3:df:9e:2c:11:9b:99:e4:e6:83:b4:61 a6:35:b0:91:46:3f:9c:86:74:c2:f8:2d:0b:e4:b6:9b 3d:dd:cb:38:d7:73:b3:65:c4:3f:f2:96:09:69:bb:d3 b0:b3:73:80:66:83:45:48:aa:ef:34:1d:cf:b2:82:9b e8:9b:29:5a:3a:fd:b2:90:b9:52:be:4a:ea:f3:fd:c1 6a:d4:25:d5:79:cf:d9:85:b6:62:d6:da:0b:d0:b2:21 26:37:f1:ae:d9:74:cb:35:98:73:40:d5:51:e9:91:dc b9:94:d2:36:e2:fd:b4:72:fa:e0:6b:a0:c6:c4:e8:fc 29:d3:2e:94:c5:d2:66:94:34:f9:24:29:6b:f7:ea:bf 8b:dc:23:5e:04:cd:76:a7:4e:a9:b7:e9:80:cb:be:d1 5f:c9:c5:51:ad:b5:f1:3f:af:e9:51:8a:53:c0:d3:d1 prime1: 00:c7:2a:e9:5e:01:20:1b:cb:84:6b:17:7a:73:90:6a 5c:41:dc:7d:ee:95:37:34:da:08:9e:c8:51:75:2e:51 82:ee:6f:75:50:26:b2:28:ff:fc:d4:da:c1:37:76:84 7f:9d:b7:a2:1c:68:6f:96:fd:52:ba:4e:74:bf:02:cc b6:bd:a8:72:0d:f6:78:1f:98:b4:e0:9b:6f:47:e2:70 0f:f2:20:78:0a:c7:e0:61:9e:02:81:7b:40:fe:08:64 fd:0d:0b:f3:54:4e:65:60:10:29:a4:b4:99:dc:61:f8 3b:20:e9:a4:8c:9e:ea:54:b6:96:0e:9f:2e:60:9f:23 bf:ae:84:01:7f:7a:77:5a:66:d9:73:e0:25:f9:2a:49 79:37:28:19:39:3f:3e:ef:94:f3:e7:3f:e2:ef:f5:ab e0:b5:dd:18:28:3a:23:49:8b:a1:87:8c:e3:0b:f9:ff 38:c5:36:74:10:14:ca:87:3c:82:0a:83:e6:75:a2:d9 7b: prime2: 00:dd:0b:83:d1:10:04:08:39:0a:4c:c2:78:05:b4:70 91:4e:b2:66:2b:de:2c:c4:3c:2c:30:17:d3:29:10:cc fe:79:59:fc:e0:59:ea:26:6c:19:59:15:cd:09:8f:a2 c9:04:7d:e1:b4:0b:cc:02:cb:88:20:07:ef:49:0f:75 71:b3:be:a4:9f:e0:4d:24:bf:d8:7f:a6:f3:e7:e6:a2 cd:05:bd:cc:44:67:68:67:43:0a:f2:1e:c1:6c:25:2c 9c:15:27:f0:ef:75:45:d5:f7:c2:4a:65:a5:c1:53:7c 5a:cf:d1:f4:4a:5f:6e:96:3d:69:82:3c:36:51:04:37 96:ff:e5:d5:ae:81:0b:fd:34:ee:13:94:0f:54:e3:3c 81:d1:2a:c5:4d:bd:3a:86:84:80:47:16:43:7c:ec:53 24:01:2e:52:17:ee:c7:6a:d1:77:70:bd:03:b2:4b:62 ad:20:b5:36:ce:28:4f:89:32:0d:95:6c:e8:45:ee:3d 57: coefficient: 13:cf:5c:7a:f5:3f:ac:3e:2d:65:b2:66:3c:43:d8:0f 75:90:e8:02:15:c4:a5:52:73:bd:0e:bb:86:a9:6c:bb e6:de:f3:4c:d0:4f:67:db:f6:8f:ce:ad:09:52:62:fd b2:44:c1:1d:41:c3:2f:0e:35:5f:83:43:bf:8d:98:9f 96:01:42:73:9f:01:0e:53:84:14:b9:99:ea:0c:04:14 f7:53:ac:85:4c:c3:51:e6:0b:96:bd:d8:64:e2:fd:72 5a:da:c1:b1:ff:6f:45:31:43:e7:a9:db:a6:9d:13:42 26:53:2d:70:86:d8:de:03:53:a0:53:5c:dc:a5:76:6c 10:c0:67:a8:77:ae:b3:03:28:12:0b:90:f3:ed:76:ff 08:04:a0:c1:a0:28:52:eb:bd:e5:76:78:5b:2b:92:7c 19:dd:33:39:2f:a5:6d:09:98:d5:fc:3c:1c:c9:71:14 09:e3:02:e4:3d:23:c0:4f:18:c1:c6:99:9e:91:db:2e exp1: 08:fc:81:ad:11:25:ee:bb:1f:0d:69:f0:c7:78:13:a4 78:00:47:da:54:f7:39:b6:40:bf:51:50:83:96:04:6d 80:ee:9c:7f:72:4f:85:94:0f:47:57:5b:72:72:31:86 44:8a:7d:91:04:91:4c:61:bf:b2:d2:49:68:38:eb:1d af:af:02:fe:68:49:81:3b:75:a5:d0:bd:93:a3:be:e4 a9:4b:17:bf:7c:c7:3e:00:50:22:a1:7a:0c:3c:3a:ba 44:35:6e:d4:35:f9:52:fd:47:b3:bb:c6:59:70:3e:30 04:cb:25:f6:86:51:12:63:6e:9f:d8:44:d2:6d:3b:c2 b1:50:19:75:34:04:60:9a:d5:62:ea:11:2c:8d:e0:e4 cc:3d:4d:ee:0c:51:7d:a3:dd:e1:68:3b:88:12:30:a0 21:f4:88:db:7f:cc:09:cc:78:0c:52:aa:07:e7:4e:c1 b3:fc:41:fe:5b:c1:cb:9a:4a:4f:c9:25:c3:d7:06:33 exp2: 24:d2:37:3a:0b:25:f0:cc:b7:a7:83:b9:84:91:c3:32 a1:5e:5c:60:b0:58:da:b3:7f:54:df:93:20:43:19:32 c6:ba:33:c2:97:97:c6:a0:b9:34:3a:ca:75:ee:44:5a a1:f1:ea:38:18:c2:fa:30:37:53:c6:9e:98:98:07:a3 52:22:ce:bf:87:18:b2:a7:76:84:05:26:9a:19:b4:42 dc:d2:fa:04:e7:08:e0:32:ad:cf:19:4a:75:1e:58:29 03:e9:2c:5c:67:37:a3:e5:ea:aa:83:f6:31:97:1b:9e f1:01:73:65:34:32:72:ba:76:29:e8:a7:cf:a5:19:31 81:1d:23:14:37:90:ec:b3:f5:78:b3:70:3e:5e:c0:04 8b:f8:48:f7:a3:2e:ed:9b:82:d6:d4:a1:97:5c:b2:98 cb:cd:90:85:46:14:57:f9:de:a0:9c:0b:d2:96:76:30 8a:c3:45:06:e0:76:27:4f:7c:2d:c8:ff:84:2e:a4:6f Public Key ID: 20:2A:0A:98:87:96:6E:B0:2B:7D:8A:BF:8F:30:4D:53:8D:BC:D7:93 Public key's random art: +--[ RSA 3072]----+ | | | . o | | = o | |.o.o o o . | |Bo= . . E | |** . . . | |=+. | |o=... | |+.==. | +-----------------+ -----BEGIN RSA PRIVATE KEY----- MIIG4gIBAAKCAYEAq/kA28nsNll55Usj4kw2kR5Rc7v2MVV4KR1H9TkI58YN67GK vO0wWtOfEeQ5KnScLcCMxy+M5V6yv36tiwxU3kvPb0EljMetUmshMQgijkKpE7O4 6bfBstTzcVXgnpMlysHr8EQLdHVXmywDcMtcWjpckF6UsglLiSJ9Y65giSD+8ivB CZzkl7jKx+BWW0QtjpEF5kuQBE4oGfZaU8bgdm7pKXoH+XTVVt0wVv7oB/f8E6Er 5IrK3Ib/yB8ahmO7QAA6PGt9abSdblEW3mNbR0LcHagbo/bd3Vn5s0nQuEU8hs8M sE6yIE/8Z9m2oFQjDc8YgIx7YZqLTWe14zZTuiGTCQwSV5pPB/DX+CPB0zQD0X12 FJFZh8fNvdPT56QvVFdM/5u79iUlCr0GB0nrPimp95/0Ynu/3zlFBrj4aM7qeYE2 rj4FbnvGLWBmNAzXi8CuQayJkTPWqQ7lCUPC0i2unHeOUsz6devhieqgikExJ0nZ k8noNZPi+tYfhDfNAgMBAAECggGASezEHbbzP3m/GH3wcvroCgHKacHG1vYyrRnV MOjPlzJgEY1EYmpjeue1XW+J02JFMLWwzn72RjMrC35dA4TNhrF3/g83IQlEzEUZ A4bHs/ebzshXGMDRFxrLe1C7Oe9vM3WhAqt9cRZwDlghMn94t6CW4ciGivHL8qtM 02jGPqxca6W7WXKEIWRiZwFcneb03nAg5RpeUjt2qZJoydKX8tFCkX3Pp8A9ZRW4 De2NuL81MQr7X0b6ZUny8gfM0zBTPVDGQJMyBO7lpDIbBwzRh71JzQ/D354sEZuZ 5OaDtGGmNbCRRj+chnTC+C0L5LabPd3LONdzs2XEP/KWCWm707Czc4Bmg0VIqu80 Hc+ygpvomylaOv2ykLlSvkrq8/3BatQl1XnP2YW2YtbaC9CyISY38a7ZdMs1mHNA 1VHpkdy5lNI24v20cvrga6DGxOj8KdMulMXSZpQ0+SQpa/fqv4vcI14EzXanTqm3 6YDLvtFfycVRrbXxP6/pUYpTwNPRAoHBAMcq6V4BIBvLhGsXenOQalxB3H3ulTc0 2gieyFF1LlGC7m91UCayKP/81NrBN3aEf523ohxob5b9UrpOdL8CzLa9qHIN9ngf mLTgm29H4nAP8iB4CsfgYZ4CgXtA/ghk/Q0L81ROZWAQKaS0mdxh+Dsg6aSMnupU tpYOny5gnyO/roQBf3p3WmbZc+Al+SpJeTcoGTk/Pu+U8+c/4u/1q+C13RgoOiNJ i6GHjOML+f84xTZ0EBTKhzyCCoPmdaLZewKBwQDdC4PREAQIOQpMwngFtHCRTrJm K94sxDwsMBfTKRDM/nlZ/OBZ6iZsGVkVzQmPoskEfeG0C8wCy4ggB+9JD3Vxs76k n+BNJL/Yf6bz5+aizQW9zERnaGdDCvIewWwlLJwVJ/DvdUXV98JKZaXBU3xaz9H0 Sl9ulj1pgjw2UQQ3lv/l1a6BC/007hOUD1TjPIHRKsVNvTqGhIBHFkN87FMkAS5S F+7HatF3cL0DsktirSC1Ns4oT4kyDZVs6EXuPVcCgcAI/IGtESXuux8NafDHeBOk eABH2lT3ObZAv1FQg5YEbYDunH9yT4WUD0dXW3JyMYZEin2RBJFMYb+y0kloOOsd r68C/mhJgTt1pdC9k6O+5KlLF798xz4AUCKhegw8OrpENW7UNflS/Uezu8ZZcD4w BMsl9oZREmNun9hE0m07wrFQGXU0BGCa1WLqESyN4OTMPU3uDFF9o93haDuIEjCg IfSI23/MCcx4DFKqB+dOwbP8Qf5bwcuaSk/JJcPXBjMCgcAk0jc6CyXwzLeng7mE kcMyoV5cYLBY2rN/VN+TIEMZMsa6M8KXl8aguTQ6ynXuRFqh8eo4GML6MDdTxp6Y mAejUiLOv4cYsqd2hAUmmhm0QtzS+gTnCOAyrc8ZSnUeWCkD6SxcZzej5eqqg/Yx lxue8QFzZTQycrp2Keinz6UZMYEdIxQ3kOyz9XizcD5ewASL+Ej3oy7tm4LW1KGX XLKYy82QhUYUV/neoJwL0pZ2MIrDRQbgdidPfC3I/4QupG8CgcATz1x69T+sPi1l smY8Q9gPdZDoAhXEpVJzvQ67hqlsu+be80zQT2fb9o/OrQlSYv2yRMEdQcMvDjVf g0O/jZiflgFCc58BDlOEFLmZ6gwEFPdTrIVMw1HmC5a92GTi/XJa2sGx/29FMUPn qdumnRNCJlMtcIbY3gNToFNc3KV2bBDAZ6h3rrMDKBILkPPtdv8IBKDBoChS673l dnhbK5J8Gd0zOS+lbQmY1fw8HMlxFAnjAuQ9I8BPGMHGmZ6R2y4= -----END RSA PRIVATE KEY----- swtpm-0.6.3/tests/data/tpm2state1/000077500000000000000000000000001421141172300167455ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state1/tpm2-00.permall000066400000000000000000000075761421141172300214410ustar00rootroot00000000000000«6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@g*ð‘:|,ìºgyÃh­WÛ@†ÁUƒF‚<^ÇEØ>¼rGôb×O½ôª'_”ÍN±ˆ‡%½½Â•ÈÛ׃WÄ:Y@üiøç’*2–‰Ž¡'òQL¨÷†a¦åWÅ^ß¾¦2°ý@Œw+¯Ñúwm’œî’<„Æ»ýíÚ‹¬¬NïÉ)@Üá(ƒÌbÙÅ*ãˆw_ÜqÕ —‡9ЇÐä¦ëWœVįèž<¨B_º‡D$8‚b|°"þ.ák3XÄŸ`Ù@‹¢vÔy!ª8‡réAàοh)sÏÂÿÕ'ò Çõã¡ûœ¶6‰ÉÛƒ•M¤‚ú½±,GâÊï£ÜeÑoÃZ@B²F.»ï©[|CÞâ"Qâñæ\Aºõv9ñÑëòqÁ|»€âZ”©ËË¥®†ŸÙó3±Pr’¤ê–ÇÇêY@ 52°khjÄÊ4µ«aÙ¼¼<û+¦ëªšÁ\÷h1Íú})u ª}‹g^­>#Iæ ÌV¢¢ì`°Aøð&Œn!Äkæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èèÿÿ€ (Vex‡xoè>¡GBRD0€(9‡iÔ®ÃHÖýKƒZ“°þ,Y²ÚUnIz#Ùeqánu€½}χœøb‚£E#2@˜‰vgsrê¼@   kè.¯SFþ« O"Ãìü«6G#swtpm-0.6.3/tests/data/tpm2state1/tpm2-00.volatilestate000066400000000000000000000212411421141172300226460ustar00rootroot00000000000000Ecx‰@x@@eb dluohs eulav euqinu laer A .eulav euqinu a yllaer ton si sihTVex‡xoè>¡GBRD0€(9‡iÔ®ÃHÖýKƒZ“°þ,Y²ÚUnIz#Ùeqánu€½}χœøb‚£E˜‰vgsrê¼@   kè.¯#2@³6‰’º& ŸOÓ—Ô€Xâ–«ûC­e¹[>Œ[‚ظ…{à&ÐäûÜÃi¹5àÎ,SÏÜ®„}þ®Ü[@ãæ £r0mƒŒXŽ„B;@  ÿÿÿÿÿÿظErÏÂ_0»¨üvéÜ%)àtB%)\»¨/þš9tþš9tþš9té_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ ö…˜å†æ‹—)™`òq}g‰¤/š®¨Ç·ªy¨bVÁÞ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ 0 @%6d®¼6d®¼6d®¼A cˆø#Æxu0cˆø½›É@g*ð‘:|,ìºgyÃh­WÛ@†ÁUƒF‚<^ÇEØ>¼rGôb×O½ôª'_”ÍN±ˆ‡%½½Â•ÈÛ׃WÄ:Y@üiøç’*2–‰Ž¡'òQL¨÷†a¦åWÅ^ß¾¦2°ý@Œw+¯Ñúwm’œî’<„Æ»ýíÚ‹¬¬NïÉ)@Üá(ƒÌbÙÅ*ãˆw_ÜqÕ —‡9ЇÐä¦ëWœVįèž<¨B_º‡D$8‚b|°"þ.ák3XÄŸ`ÙEcx‰¿+¬n"KC)ò3ý?©hÍmëswtpm-0.6.3/tests/data/tpm2state2/000077500000000000000000000000001421141172300167465ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state2/pwdfile.txt000066400000000000000000000000121421141172300211320ustar00rootroot00000000000000mypasswordswtpm-0.6.3/tests/data/tpm2state2/tpm2-00.permall000066400000000000000000000076401421141172300214320ustar00rootroot00000000000000ëVFCåŠzËC)–©$›©ÿš_W0F!áp“ë8z=ÐL¯¬Í\«DUA´Kâ|æÓ4æÚ5‘àÀ7ëó™*;º„QHïðNeÅ;<9«©¬¼õ¯é-\Èà5¤¦hqQDÇ1Àk€”4lv½—¿CCb÷Cös¾Qyf£#Ð;@2I™<ó7‰.1Zä…OÅbîc: P#ÀÓ.q&âCoÊog࣮hã&%yVBq mÄJr Læ (!]±‰~C¬‰‹—mŸûûÜ” Ù#=s;t“©gòÌù^4øð|”>IùVQ·B!¾nÁ­;™¢|n:ôVí­ÁjìÊ[sÙö À$ÞºzÂxê— ²B!¼€^ õ3î³[kö¦.H^ö`~µË—­J]ÁßÊ)ËvIŸB”„÷÷\•U³‘à gŸöÝå(%wΔ–ŒÅ"|7ú7"x·ÕTÚr˜Ù­ÚjÍæo1‰¿LîIñµAÿqÌ%â—8´•Ëá‰ÀgÊ닜 I}ZÓ5'ަîÛ—OÞ‡÷˜ ßµ·”a>@øÆfSÁ-@šç~ßW5€4ç×ý$RíÔ^úƒ‹±˜äÿJnƒ¾X±b"Êù’…`Áj³Æn±’i‡r‰ÕKRLÝ7q¹OyÌvØÆ·üš‡=“me L“CUÜc´Ï¿>_9ð¯M$Õ]¡ ZÉOöüHh ×ÊØwu`“„gû[ñœØ‡j†¦~ì<%Í×ß*óvÞ­ßùS_ß8¶UêUÜà…+öÅVØÒXXâ©yäŒÇ"”ì!67ÇPí.ŠsŠ;ä”2Ý`b‡gäÌ«|Bõ˜úPh «ø ¶»ž8Pi¬I(«fÏ/øf«¶)#çUŸF/¤¤äL)á —[6Úy°iŸ …‡Cm:¥íõôô­µÂÓXêÃŽ(»×ð®M"?-°ôçe–bc˜ÈškM‚I'áïŒ_í|5‘¼ö•qWÃ7Ù‡ÿ…*é÷-ɹƒ­7†Aï쪢„³»ÔÕôÊ¢e=•#~çiò8;b'\:nCNñÕȇóe'éü‰ø±2¨EGÑÖç \ …:eª,͆®ê·Á´u2xY—b|$]…ÕëMCX]ÊJ®„—=›ÔCa¥ÐSKXב³`Eƒ•~UU,yr -g ²„H ÎÚ—°ï$Û&! êÖÁ6Ù ˜j_+Ì{åÆ:dñ±r¯Í¹ÙyЃÞÙá¥q–ž€«J*Ó\VƒÔÔ}œû^Û‚ÝwJÎSR ë×*š… æãþWÞ‰e½ðÒ_íN—Zµç—Ênà”¦NGЂ½4ð‚éŸ{‚¼-‚ÑF²··SYu“ÎA¨Å%«°œIKÚ½›f™9”~˼‡ BÃ>4QêJ°ó­×šº Mv2#yô»ÕõÊçM O0µ5PëDÔ{ˆ‚ˤùh0m’~°óó.Õ¥°â9>xô~ƒo³è•+<Ä͈qÝ(:l6$¤- èÊÄŒîØ5޶ˆ-ýú—íó(dB>{_Gö…¨Ñô4Ä`ƒÍp†¹-$«ð2þL£Âß=:¢xøØ®&_ªYY”†„ÇÝz))f°¥*‘§‘¹ß–]ò•ý é!’›·íD ª¯ê¥{Êú ³ùó*–ÝÏb¿ÔÑÆÐJͮ⮷³ÀàY ršSf‡]˜w £(˜­ÃØjð¥´ÐÀMÞ“Ñ,¤•«NM¨4‹*ü @ ñˆÙj–ÔÍm$|`H­ }²h¢šT€{ ŸòÏH ƒ°&h*}ÊujÒ±W…ŽZ#ÙÍ-$›ÚJ–²#H$€ÐWåèæÕ:œsÿèñ²*…LÆ3)}mMEGÓl«aûÀ¿|Š?uÍãhEn`ò“ÁƒÞ~LÖÍÆt¶Wª› &1æl[…íAœ L–éiFænÚ™X³˜ÄtðµÁ7eG¡§Í‚?לÀààoû My̓åÒ¿¤ICƒ†`•Ù„ÇÆåncvëTþ$PP$ÁôÒ\ó€Ò¼cÒt—KÞLéùwÁAª¶¤.³ó^|y@øß`¶&w´pΛâhCU‘Ä.1=¶]ȯf÷Àzµ!yÑo æñ¦.ˆ&š½)T‡}™x˜)>(ÿÛû‡ € âÕ¨Æþþ6†×¯ñ ³ ÞS`&Ð$¨Ä³d¤2á´³oƒ_ïP¬Y½ wƒò³[ßÔïTo¹­ ò_‹ðÁ'ôÊȨ1“抦]‹˜1su>‘‡VÙskpšwó£ÙFлÌÝ2O@ªÒ,FeÍc™ ìš2ðþi§ˆ*/jÈðg°ÞmŽÝ—Ò|´g‰~ñ­j)FÄ$¼úbbPYjž®0¯9×êø 3ËŸì¿G®VDYŽÁ’¨ew÷Û£ü –ÈëÅKÑÇð¥È»Y3œ‰ÛÃð¿3>Ê!šN èжñG ƨZÒFÞœì~ê«Öˆ]Åß¹±²XÄd-ŠsK~âøm˜æ;`I Yœk"úÿ¼ÄÚsÒª€ù,˜æ VÙcAð'Øoì¸à›ù‹Ž«_ìÏ.Ø×ª få;x.Õ=;ÊÃÚ¼åS%¨Ìo6¯¹›ãPöÊ–ê†[„oJýüû(Âdó.¢&V¡Ú… Qˆ¼~ÖÝù‹MÐ'>˜Ïœ®±{éÌÉ÷ŸF˜kŸ„^꘣pœ¹œÄ3’š­f’‡þ¹‘Z ®þL§žJf;ÕKê™aùÙ4QÐÆè PŠçsŠ×¯9¹ÑB)5xÖºÏ KûQÏ Ÿ_°êcÎaöè‡'Cn`¾ ]«Hùôá%Ÿ‹ ”±ŸdöUºO”Ç #PáA1k4­½7J@ÅiÓÔ¶~´ßëbS^$çï7º¡7!]72t=ŵk‰Žùm —Ž“öm™³hÆM â"[Y¬þ(ÈãËþ#˜L{,æ¿—rñE—…Ï¡L ­I¹m3˪î‘fBôÌœ´¾½êEZ¹=^7Dæ'‘ð\Õ‡ï3þG²HSFY—Ö£=¡ ÑÖ 1~vMPÒP†—ÁUÛs;£+ûiÄOÛÖ1?N·Ž7(,­à3œ×%GžÆ_‘þ²Êªœmgà.È L#>Îw£Ï]ÞpXú#„Å`wû$£áDðÂ&µ˜ŸvHGI_¸]Z`ð41;ñ{*U 2bľªõÍHë]º ·Ý ÎÂÿ½†_L0Ïvæ6È»Û}ª­±±JhóIJ…Öq–©kéù}æåWÍÑ3” 7¾EYLjFÏÄÙoDJZó/Ý&Ô[C1º6ˆ 1œð"‹h¤EÍ’;IdÖ€I•âƒ]*Ó¬¼˜¢W/g^k$oÛĤÔÃSÊv€°³k’ЖÄè½úL<Å_Q/†´³ÁdñŠÙ°®_géAÈrÅ*YµvOŒ¦ñõœÁ€çìªI-øõS\sN’ZÆÃª(¸<[‹q»{%Õõ/{pvƒýù›ÊüßVs&giÜåÛpZ÷yTOô÷ð„²a“oö/˜´%Ä)¡ûÃå”j7-ćîÇ̘¹Aÿi—Ó ˆM'‚7¥i»$UئرsަĦJžpÍä¿Ë¦^¹)'q.ã Hô‚Ê)’ÈÐ:A«ØãˆõX©Dî€7,Y,©;nöŸe£öµ‰ õ«Ôƒ~¿Ñ’öm#—G©›ûç¯ÀºúŽ»ÊQP£Ñêý• ¶2P·Â MíU\Îy[än­ÒÇޛɉN½ñدãS2”äèøy;,ê[Û‡ŠúDÔtob+ë5€åÄô–×§xBK$¦ç½ù²¼ Q³ÙH~Í#*ì$‚Ë®GzkCîÔñ+ŽËæE°Ýd¯õ—sÂóË*mŸÓ2-B㠆ǫÎ<’Ïüþ•Ű`¼BçWd;A)}ÕáïÀ!ü¨.Cï­ó•MßÓÏÈ~í)ÑȆʂÙ~ØÛ»'g`艺V{™¶LÂsLÔÛ d1l\6¥†¢{*Ö¸§™à+`ÈdÖ%Ù–Yêãèz¿`„ ¿è'a÷ºÑc–ä2Â(øþÅì4eΤ U?æ%-8£Z©€|ÅñŸ·åÂKÏç€þÙ\*‹¥ß¶¡/ŠD÷ =Oðe¾à‹­G²  ¬,’ÁFA@Õõï &rr}sç¾úz™w½!9T‰xà ðI°Ô—w%õ`H¿Ü^/è0¡ÞUëÍí\~ BG..eÆ,­æe1f-²7À¹¢ü-h1!H/lú¬KéùtËHOš'[§—CŠõØ€ù"²ú€Ý±<Ų@`;¾¢9°Y,˜Ýßk$ðx"Cox~T&°מBSh#Kæ_5–A[ß$\d+ßu£…}kàйåm?Ãmw/N1Cƒ*¾= vW3”43ÜW‘Q܉²÷|\R4…¨[&Ù|ú¿›¡²¨"¨õ¨Y•N™ 3.ƒja)j«ñÕ)Æ&Ø‚Ýf “ë$¹A9£×оZE$i³¶¤ì94¤úØ8„K{,¡áØÞ‡ùú!…øP¸>–#T2ÍDÙ·¥ïh`Âaû&í<³‡lhÜp¥Ó!YqK }[ÕÃ.Mó‰Ú•ÈÄŒoÄ—»Sµªu'Âq?ÓÊ–Éâ†Óœ Ù‡’|‹hF tLîÄ*|Ö³sÏ€Î:bÀˆ¢Ï½7®¬fXÀø.\‹ò4t">›‡2É~ mîÖÙ¿Êíê,ñ {&Ǹ²Î¯Õ?¸ð?G$,Ðv—b²›7LïLe…ƒpW#~Ë÷_C’u•ü?ObbøØ3DÒ ,èS(Ý!±,ŠeÝrƒ´BQ ñÆXª,»Bî~ËUì5ÉNWŒï­ ÿdÕWP˜ü–º˜|Þî7^Üý|ì·¾œ.FMìK´ù‡ÖBÞºs›rHŒ^Ûò—·&Õ]uIê»ý‘®–Žc6vÜj\[è‚Ó— ç©5ZÔF*>š„2[Òn±Ã¦ບŒjçb4ÆÁÎçâ ¾mËK™ôù/-„ñïÅ®w zÂ<ìæð(àðõ õZû¸ÄâÍ’íIúR"剦.4¥oAˆšqSOÜ9¶±\ªëêô®QRyÅŸz'ß—Ût†,^SË==CjŸü×¢´&¹–¼ TR›mswtpm-0.6.3/tests/data/tpm2state2/tpm2-00.volatilestate000066400000000000000000000213201421141172300226450ustar00rootroot00000000000000-E1z4ãŒe < }³™á,„)6•L‰™½—qu’– CšÆÓSKì w”¹mF…!N®~=Q]5ìjÇDºë™„£ Òìó˜çTx©¥«|1™OéÔ™{š!Ÿ¥j´#…x‚qƒ€Ä ΖQ^ Ë*팼Ý&u~¶¶nxFÖ#žIp[Gã%ÏK0ä¨@áïã™ïÑÕÖ$Åø,•±É6•JË-7©Øc¤™[Åß›UVÑ\%f§±® ¤rˆ ç±^˜÷OJ ‡#­YŸ.ì1"DZ˜),‡Æ ÷&ƒ˜]àW~zXäéÄÞµy{\Á ¬O´/nY»3…µLo4þ­Û ¿4”¶îQ•³ßm¥A¾¶®ÈiÞ-¡œÆœÐ3¿Ä;d³-?N×ì­$¬*ßÚl$àÚ| "õá)^)ÃeY/ƒ|¨Öé.ÎXJ¾þ¶0Á5žØ[·zwZÞÁ:Ý&Ö-gÿÀ OI²½…opwN]ÅùÌÞçÌ{_ƒnÌÀAÿYY”˜hÝLHKöqn)¶sÈ'süÛ|\(O„µ0oTIÚ²J—™EžI[?6¹j­¯œl÷Ô¢zpÁ6­?NPþ#—+ü5!ê(­gô]^ëâ’NMÛÕ<„¤eG2?öí¶®ÁÔüS·É³šÕ}8p3â•áó›cˆF\#ó¥1SÒ{ÅÄ}Ç õ¬CO£Ú=[žKæB$ÆÊOkÙœJ ‹eu9_ÅV ¡Nk2’ÚVÁÚ€>{Ê ˆgðÜ‚æ³q_g=SyOÒÁ¼°;ëè´;¾-qÂþ¤wki >›ú<Þ: eQ•bIìeí-Ï–ÎÍm ØôyóFÕØÖB¾Óó„8Ñ€;p͸o÷A¬çr?¤q<ô¥;­î8‹Yg­/ 3¡o8byBÀ&bëµQ¡Ä·wš^0iKC£ÂÉ-É:b†lwýeØt7Ž6e@åœ둿ɞĻL9>î¨ùØ{)ç¥ÕäzÐÅfRã¤t˜Ä¶–ç Öl$¡âAŒ»v™kq¨«’¤»L¤â™g©ò€M1÷sO—-"9µñN²|ÿ€?Ò•q©Ës›±õ[¼EÞ ªž`¼tÝ4ž˜Ù1QuÄùˆ¼ˆ|%- †"`½ŒÌœÁãQ¸ZÏlõ­òÜIJ¯“5Ž!¾Ãª:ì—!uã⇓ü£]‚òv‘d‰>¸œãú‰:õD4M!2NÒ44!ivNìòŸÀ—÷±ÌÖú=ô*¦Dfž–"•`ÉÒ÷|K1 RÚ Ü2}•w˜’Öš;X»è÷vO×צñ3™ô¹‡KŸ!SÇ…0¿´:×È {‘†ed Ä^^ª}Âﺗ©Ë­Z¦ùŒ˜1§lÝãi›(XL/dS£î¢?3©„©-Úg±eÚS|åJ¾¸ª2—æŠ%ÜF‰iÖH< ×qAXZyÁ.åÓ¡1gÓ)o1Æ©é¼nrf´Ë!ÆÈk÷+9CÖ=}·«Æ˜)¥ñ}Í~ÏÅo‰kóßåFŠ®åQ˜Š&„ÏÀ`Ÿø±#§‹OäH’ù8ʽüŽÁO&b› ¾WÁ6—ÒfEE€(çãËXç“À{xzÁH/þ:ž¢Z_Nî­ÙòÄÄoZ£Jß;þÐÑã|ÇY ¨u®ÆáW!"lÌl)óèùþߨyJ5Ÿ·®4YÌ÷JkfÿéèÚd›YûÄÁ2§IŽþï`$eâ<8ôgVúAÏõ©ZOv[·`Ù Û¼ƒ#¿‘bPTCŠe{á Œ|³lëƒfA3X0>ñòPfdPås‰G¯½b¹ßà•à™n]y>dÎ}±ÁÕ¿’&FÂð;ŸvH&’rß©žpvúi8‘% r¤öG†,—{µG©—4€ð<7¸'§²yx×À…«Ðó‡š~„µòO„ž±ñ_Yµ­ò'VÒÂØoõG]œs&:ËK«ßäÓnÊ2̓sLóH9dxëïÞ²Gè¨>8®ZÒglb8MŽ]à$¤}o0Ce¿f +f»|B¨îZñD3‡Ì Ë#†ª›(!]÷ µ'w-æJ>dn àÏS ¤ÝB6³Ža*{² B¡¿<.—85S‚óœ& %!Rl¹Ñ§Md¢¿—œ•ñ€X³Þß·t´x–Ú@Å©@¡‡yF‰=Ó¢­ªù>ÈúˆRœWÊ}Êàáwh‘Î+-¤©¡û“É=+Õ<¨ ö—›Ì한^´)] Ýé’µMòÌå¡#î‚‚AÄH` ²Ñ¸Ñ[”õ9ô°Xkó\‘Ï@nÁ/¶kªŒ›©7øÞ¿8´S–“1£ÕŽlÚm¬_â#f[à.{X殡Ĩ€Aœp§n+k9.l³C˜åŸU:(¼¡é”H×,ÈçÉ_î@N ðÉk¹1ͬnÅéxc­Uô†…cîqÓÆ+~⺢Õk=“DB|–sΗA‹g‘x6ų‚…L²ý+úس£Þ릹¡„Ÿ1sIrD^œ· ŸgfªáœÇ|”¬k 1(–ÍŒ“0\½ðãÖÚŠâpÙÇŠÏÍüP¸ËÂ߉âƒï¤ìÈ´›«e‰®¡TxÈQèëDÔîƒý±Paÿô gé’£ýù ¯üòPëgWsßËûûüU'&boâ6â騤u˜ÕR]%qƒ&¨tÈçV+qû$þÄ£Ð,#øYƒ²?9hbé©§i5ZzucØB*±Ï4ô`“ÙÌU%u¨‰‡IoY@&¶›()W/I­AÞóÚ¨ô?ÏБ¯;aæA¡¯ôîð˜°Î0+·ý-Üs(.äô6›îŠ hH©êù¶̿u²Wé¬ÅâÅ+yŽ›uÐI9¦~¿J£áWÙáZ‘>ϼ¿Nr—i¾tÝRÍÝ=`$4Q±3I6oÒœêJqÔ®> Ø¡õ_¼¯\ØHaK©Î€´Òˆkššßû‹åmƒÄX¦ÜË3)—7 :äqmÆ3°$w7fÁÄw­JhÉr2ªn^þ*M8|‰Û4hpCÚákÔ˜d}K+“{× Ê©}I§òG ¯ªnì©Ó¬4]áÈá«3ª Aغ‰Wžmø“?ŒY1lý/øÊ!Œ{¼Ú, ³ôJB«ß3ÅÊôÿ¯yñ~[•æD’ˆ¬Ví¹ (÷ì°äÿþte ·ôÔJ²OÖ¥søÈ²}ûAnEbRC³5Ý:Eš[òêÖMéÄIl©M&k±¡&ƒ¬¼ÌÅe/ð«‚|»VK‹¸x5±î|WÜòÑB„óW©"qCµÿ‡lŠ{£‚ËúAœÊmäŒz©ç|,<§ Æ3½ cîe³oæ°Ž«V¼Y_ÁeÝldHX•ƒn$²]¡\ ! å.c?€ÚÅÁ½Ø\‹–É)OÊ«ž€ñÂï Ìé9ª!òn° ‹˜¿*iËÖçDÐ.…üæ]5B ,TÑEïÖý5í :h4J8 Úš—UU áüPÙ±Åøí±ôµñaà{#60:ö[X­ÖË»…LG;¤þžùsÝ’RLå|úÀoïaÛî$<ƒ?k5±´ìò=±r—»˜ÔIF¨®n ÄZÑY ÖT~Öt¥0®+žÈÁ®~U£{fŒé€ØÏùõ>AF¢YˆªwL6„>\G¸¹€_W̹®®6ûåtR³GûHuš·JÕ6U*Áú+ìÆÂ‘¡ˆÛ]}ÈÈ>– ×Ó!±Òíœwl;ò©‹”1àLT‚"I Ûß›t'Zµ9‡¶'ìDQ>èƒAÔñ¼‘ŠÙí[¬DEŸÛ?'DeD]H/ô½ÌˆuÂrc~¯föã™ÂTŠ6—Ú,}FÒÒC"ã]ãH•Z¯‡~‚E¾7jVkœá4òÁ©×s¸Š“?Þ÷VI©lÓÈÖŽØ…ÔcãÂgÝJÜûe¼Ù('l Ħõ]ŸêîÅCµ¥7Ð+‘Ô$üõvêL' :þSe;·”öuE”—c_Ks^"Gèû”Eë§oœÅ§ÛþR‚ã…ßê¹£ b ëÐ.Y¿Ñk¾\“/]tªšG{ïºRøØK¸ÄëûíMh_P19ðE±X‚± Ý®§/˜üŒøG§Éð]G®«vÌ=ýûXŽL%ñ¡ –‘/5`5€ä8¾üó mŠ'´‹þœá¡àB|UHp©‚jÕÂFdË<È ¼º^E2`Ô†’"϶UÛú…L¸rß»Žg’g¸ÏçFžßý(âh -ºµisävWòðA3„!éÐëÕÒj§Ž=·\ 6Íg cŠä׬aöÜTèËlÖ†+¦´Ä}7ŸÑ©: F:Tü‹Õ7‚‚Úü³Xæ&dý„$ôœ‹nYWŽ 9¡C_*"¹ÉÀÓ(EäÉ=ÈE ’äÂa¾¹ |‡ÆÀ Çýú¢OéØÀ€&ýÂgù~­˜ZN6Ò‹[Vòe$î‚€~½ÿ¢$¡x.鯮D©¿‘ºÿÖ>#D6î:Ç}@ëÌþ¢—Z4oAã ±$¿ ïEôx0¹@Oùüæ/í³°hví9 À©«gËo¥ÝëÀ”µh§ˆmdÊcgxTæɶú–2D¨}ÿÜjë1l‚æÖC~LÜW^¥ÝÅØˆ’¦rà¯Ñx[ vo^‘¨ŒªïÜÕ}‚¢Ÿ.Hsí,ÀY]m´?ÜHò{m1ÕVRΜ3ŒW-Ó@*6«õr‡|ƒ:ø“Ç©?xEy/¶M$°EÙ¦žüÕDog ‚ç岂|ڎ܆Þn°8ZˆC¹9«'º‚y:m'Î~®@d%±á'/ UÛO„šü¥.*¢^Å‚v-Ÿôö9Á2ƒôdzYÉ)VaEoØñÝŸËxdÖLZÜï dõ—ýA.½=$~‚$ún{”tF žAñà›Õµg_ŒÆGfA rÜñxZgyMcð *Öʧ”7¹ÎÃ*ÉŠŒ©ir+ ?J,Ä3¡ô»€aw60¾”‰Áç|l70µ%*c<†:ÑzÉÕ,V·âÐV‡ìÖ±þÔÄKože9ÆÁgX Ë,ÉJùV=“år×¢:rñk‡æËüÏ[®~££߇ޡ#u¼æJÏÙJ$eôhzþë¡ ÆV¨“­ÏrúI'8ϘØëž‰#"Ò ¼¦ÿ¤¼2ʇ]àúp¶r@T€KŠÀµ[ß^ºƒµKzÐa ¸64~ñÚn§Bœ釸U¡ÅGˆj…¥ ìÇmjÊîVýfµ ›0>n&GxŒÊºE€¡1Ö#Wçp5žá§€Fúà¯×Yë º ÈÂþdSmpϪÜüµ-) x›iò]†ÐXc@S}štRãGæâ)Ò˜á«i4˜ÕžºëíÕ4Ãi¬æÕDÕàL+ÿ”ê‰Ãø‚öîÀŸÖ8±Þl³î¦Y“¸T† 88Oúø\b;þ\–Èæ¼úد´¿›€pU;PlÙ©õÖ:€¹â–T»~‰ Þn÷}í’úé«+cú,W– èŠ0÷Ÿ2T`3öøÖ¹~–·¯Fêj¨„Åp®(#ã60%&ïzi¿•û¡@vÞËØ¤qÒæ¬„tgGPùÑrh ¿ÏÊ?” ¹×æÐ^êÑ·ÜÛ!$hÖLÜM9uvŠÕuŸˆ~NZ h"¬.—ìíu'¿äÔ?E(y ™ÊZ^à›Üò4åK;ØÕ¨{z§Ün,.[´J×ñÐNI·8[w!UV,„Z$$¢›­ö¿o¥£íÔâÑ’á—67~Z (]6²PÎÖýµÅ7‹ ³@Hé5‚½¾íL9ÌìMýÀû´èújĈÂG‚ŸœÑà©%ʈ꘨¨×$;_¿½ß3i‰¾+ÑÔ;MlèyÀ6åŒ/z?6ò`˱}솙²2–í¹Úó• #”÷ÝGá´­×õ’Ëw"º÷×h5Üæ·TEž«2Ρß@§•,Xú›Æ[“%|wÿ!`›[·ñdb+X¾­³‚U.Kdç‚A+¤]Q±³@þ”rùdZŒº /y{ß±{ò³©åÕφU’ª¿‘ÚH· Q¾Jõ¿ç½‹xíÅnL>ÌúÙ ó࡬tybkaÚ! F 05OT]úŠÆ…qs™ÂmOûPܧ+¸UùCºÇ…Ôl†Éw4;ôß(G#ŒÇá×MvLí/Í}}K´jueö9ÐiIëŸb‚ì™xÎÉ9h “&ÃIÌUË\X},µ*¾ ‡—Y§™9Hµ""-¢éê|Ë4s+²õ!¸_YŸÓbñLnU#9ü,‚øµ-É®Œ<`î“É ô.Æ,B&{À–¡'Aá±ö§PYt«ŽüŸày/n97Á/<>ûf¯ t3LqÀõé\!šè·1N¹GVC¢Ý ÎkÉA-vjHž–®ÑSĪ 8óš;ûnC2ÎCY!øÙ¢+djî~ÞäDäGpŸ/SÍú" ÷‚ùs#]JZ®wE€Z¨»·µWÉ)úEqðø@òzÆLôïšñ޹ӧÛQ)$Dqg-um4‚eÐË1uÛ@9Õ¯°öú%™ê"Áo}œS?Ð^¹øºDþ©•p:Wï¾zÞ¯N9ÒŒòs‚2ûLqÒ2"š•R`æã£Ü0ÕÅÛ|ŸXã Àà?Õ¹Ÿ£•ᜈ̭¯”Yûâêÿœ|©k¯»P‰H·–ز€l€æD/®‘8¤×¦‡³ö‘Mà°ÓScEU)€,ê*_.R'^ˆ¥ gMvÿâs‘¯©3·n.ôƒ4ÎࣖŠuAt_ž¼OÔúÄBÖ5´ Tv‘éÁî:¢ÅVy‚ERŽPîgNœà®á…B€+_ï}ÇÜ ÚõýrBXÁª+p:i‘ØDŸü×¾UfN\wÃB™„‹‚ˆiD5õ÷d7ˆ“oÜÞcŠü ]L ÍkþXU^×ÛÛ¿&—h)×Ì<YìZö}øØÃk‹,+–[Äbï[nš­ø9ÁÌ èL¿ã­*^\†‹Jz<.ÖoIÚˉaÊÁXÁÎÙ+Ûy>ª¶“°YwJn÷×9fØ"~µßÇË»[lBOyÛ½!Bk`S¸IK{?Es颪-G21%zŸËÑ{¸~n3OÿñãLóreݾž§¥%´ûeso¼¾G…àð3އ»þo9cŽ­ók•=¼Æ =Êj!Þ’èÅ‚ïC:+áEk1Hg8€N¿Ñ¬ñé‘tš‡ìXCŒð°rmãßf;ý { Œ®LgÚ3dŒSÁþ<Íϧ_æÎ8(}hq{£ø½lÛ;/}v›U籺ÍþÎk»CáÉH7¦\vôœWgY„Ïàµ69Ë“/xÈd[qÃ{ Mø]ì®g‚‚TKø$ÙMçóž$Å^Ú[KÞÅá]²À³¤ÕXQÁ mYñ&l"\ó~AÈÆ#ÌCú?PsRµ§¾ú3çôibu.ƒÍEo$´†Ôt“·L3T?F=¼›NVùÃt:ÈÍ UÖDÞjë%¯·ø¾•=ÎÔ"P!& {b¦‘ JÐ4GÊ+‹½½‰' =³äR«Âa½†A­çäý‹åDüZÏôÏ5˜^£Å0Fу3÷iõÚßß´Ö>£È—N]µ î^¦ÇÒuÀY×øè…ýXÙRþé·éêò–âÝo¢@? k8Í \ý]Ä›×G7’(dB FdØõÜŒîl»Á«BPÅϵ«ýÆ¿ï‚ðñbƒ‹í]ÏfÈl#òçS_³^›Mæøê´­cåUá„Ë1GT)f qB3·-ÌÙÅ,\Û×7Ò³ÆjŠ÷0Õ¸o;%t[ñ¤§­/Ø«+8 ÚoÏ£s‚àP”Ì#•¿çÉúHB<©É|‹(/=ìç“ßpò»rXØû˜ü-¸˜ìW•œ9°É‹8%ù› §…'$„_ûBÜ$Üÿ”«xcÚ™ “…b÷pÇù´¼8»`ÒS¸ã>‚Ì+XQff·º6䤲€XˆïÓhùÉÐ\÷ÓÆù·s°§¯¢€ %²L2|è^†õÆI'w“‰,A*8ˆ±ÔµDÖáÇ›{iC ¤8¢¶X:ðRô8:³’n³0ºíéYÕ?½^O(B3û9»ßà­ôǶ²®Ø7©=€žú$9O"‰˜³¶FrMËxF~ܳâÐlc‡Ä™‘•*‘‡••›?K)ð¦ô•ÿDÐÒF:˶f@òFÊÉ|éúùa ) N,ìÃöœõ½ò ³‹‰ìlzNy?eëÉ[ãæY#TCH5êWR T7{K² ¹ ½NÒ’§ï6ö»ÙFgä÷š¼€÷?AŒ+×ÇN 9%Ö…5$K /‰¢XNð²b½rÞ毓äó¨Ñݳ0ëâ90¡›ûáû”þ…d-j4¿Êm¾¤¸Oq!U<žQzgö— R£*ªë¯¤Ví’‡GDÞ¿C‚|r½áqÂÅÆ·N I=xF.Qˆ¾¡áËlY‰XèÓTÀdè±¹w Šº«md§”ÅÛ<êd?6å®G;_àBaŒ‘ßN£m«[8èB ŸŠÂÙŒtí ÄzØ›?LºƒF¥KÍ Ýkÿ~®Ÿ;ž¾üa“:Zšõ„»¶øžÐQF—+’ü§‘o¾'(h?Z‘–bI>ÀÝLjôwEÒãiß»1x ¥F¿IóZ¥P:”lº$f"ïÒÎÒeK(Üåºþ–Å!…¥¿ÓËû#ÍJ’6ªéu$4`Mhnj”¬#™ØaÕs—P^¡ðFðë/5½¦„·¼ä+)wŒ‘^ ŽõF s×éööç7`ÔvËeVÍÅÉ|éËå|Ä^­ï·`FP]ž0Bÿ§µ;ÎgäPR¾K„jŽ €c]s+À§ÿ*´JŠÜ&ŽEK€•Sÿdôîº3ò<ÇÒ}?ÅÒç ™²Ãü)‚P¥G/2ÛÆ‹ˆ±Ì “Ÿª”jfÅà/¿ÄÙœªÆ2D,+¯÷Kòê «î= WØ®ƒû¿9BŸÝ$ñ""µ›*Ý-ÃÙ‚¦>I–2h"©½¸çx¬áåQn¡_T.˜ÎT(0blR}I(û1swtpm-0.6.3/tests/data/tpm2state2b/000077500000000000000000000000001421141172300171105ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state2b/pwdfile.txt000066400000000000000000000000121421141172300212740ustar00rootroot00000000000000mypasswordswtpm-0.6.3/tests/data/tpm2state2b/tpm2-00.permall000066400000000000000000000077741421141172300216040ustar00rootroot00000000000000 ü ìܹIQþS©þë’W£îX4˜T"îí.¯R^Ô¨ ôçüê÷¡’ŠôU‹p„’Xy>6M±‚e'ÒžÌ}†w•}P2õVJVÙ®]Ëqø¿òˆUll õë>p„­¨ÏŽ:¬ÜÇŸ9Z(éò†­ÀC^O¦$³tñÂô,¬SÌ«qœã%¨Ã{‘ÑŽoÁ™á$è/ª¢š2á¿Õ¿Pò "©íÒmBWëááöÕЧ 8 õÔ%˜Ñií:ŒÍô÷À«Æ@øÃ2´&3Êr in´bɆ'pzP^·«ƒ7oWCï<ÍFßQÑb‚Ȧ¿±{7‰`Çtx:ÇUžX’ÎØºM‚uºtÁ7dÓÍ4>]ÃZð–ÑbáHÜtævH–´ eÌ2=‡0¼·Æ*ínÇ “®É–ˆ±½4Ò;2â&yF"oŸ=’ÿÂOã3­‡ö!éôU×—\øÆ »p9êN’ª¯zŠZ ‰:oô›À*áU`é,µ¶nÖFß8|¾AuŒÊ‹„N!Ç¡„\äo&вWâÔ´vÇèCtX^KÕš{Ùû…ùuÍÀö§Ïãý:Œ§2¨9¬¯ð”»Y´s…Òž4ŠL3LÆZ‘"‚Ý&ýÞŽs7ÜI`ap1^¾òŠ\œ6›ÁÅ®ÈkýWŸµ ™ñþè–cÏjÇnÒð|oÔ +$Ìr5—CQ¨‹‚§Áô/+=ëìj-¹dliŽ›ðcÓûoÿT$Ô”XÞv~æ8´åœôµ žbðú¼+„^-É r¾{›Åüë×_ƒ=°™1…Ð}¨¿YZœâÒî”Üñ€KŽ •®¹Gp$Š»æF? äpgoéGH³¸Xä°ø¼”rábî +7Súw[ööidÝVë/¾Éáë÷C†ñ9p#†dŠ–(ƒÆE¬ü@ª’dwþ•íÌ+µºnËŠ ž_ÀU>àÁŸ7Ö ‹ \ Å!™ÔKÂË´1×|Xëo/5¶~¦}•ú+ïK¾ñ\‘¡—ÃŽ¥ºÓ(™"µ‚fÃ2¹©þ¢H“`¦c‹Wßm96žõÚ1}UXY/’óïÚCº5,Úï-¿-á¿TgUpü¦kèêKØùk'‹J¾úý9ʾE8ê:óŒO‚’{[äÊ]âF‡HÄóÆŽÐÛœ?çûó¼!ž­¸tvÕø1Þ(Ã&Å2‚Ï‚Üûg·]˜†t5‡Ç/_,·§'%ò›”õ|¸¾î¿èšFгùÎÃGœ«Ö„˜˜^òx]+Ÿãa+¾Xƽåžî‹ûp*ÅžãyÜŬd˸§ôòÔãêè¦[ÖH$\‡šÞîÆ ‡û?MH$‚UV2\ õ™ ÍΪNŒ&{xFFq2¨)Ìl`Œ\52”ÄVù•¿ÉOklÆ=T–íØj•ø4ê)Æx"gå\Ë〶F¿Õù¤øt¨³Û!šJ“‚¹MWm†¯_SÖæ‹Ò÷øGR­ØŽ<½ òf’ˆxoÚnÞúÏ~L‚rKwq¦3”íÈ÷ás|‘wŠ<ðƒ‡hÙ ÕV‚øÞí!ÈâF‹‰VeœÄˆdxÓ\}[-b‚ÊpËÔ}ZöTøhÔ÷¢ sÆ6ÂI¹\øÁø¬©osÈwºìû ïIO©‰©è š;¢$Jˆðâò®ŸæoæJð—§I×ñ_îk˜¡ë@EhÔõëB=€XÖçîÍç{‹ùŒüê» ë©]ëÇC&´žŸK²‰§ÑÜÌ{EzÖž]…B{¦½Ô{„ YB‰poŽ^2Î HqÞs/v(ÙF¢bªlóB±ºîž˜"ØœC“Buµ }ŠˆbFÄkYœ÷¾€ø>/ Mr¶\¦¥ìóïl¨‰ªîs•3F…õO«ÇÿÒ›$ð)åÕþië±jð¹‰g Ý¢6GŸ2 47ö̪LóB¿ÙÕ?µ,´x¹Wd(°º+ÔUÂÒ®âÚßðÖ«t¹×UéöhÅŒÓÄr"Bµ,wÑT¯s2OV«{Ö°ðg&Y–Ð]°v|¹µ®Àÿ»Uƶù]Â*‡†VíñãdËÏ©1Y£7›#>‘Ò®%.ç£N9ÔÈÐô¦`ÞÄq£ã;8ÆÈÛânm¯ Ù~ÇLÀBzsÆö,°ó€Ë [®%Æ^mØ^?OD܇V8¦ó&ùÙ@ÒÆ“f6?W,›æªéÆÖ›‘ƒ%J™yÿw# ºË`@oì^’¸•Ò|õÇ€¡üu§Ö÷ŒÕ´À<þ³µyæ˜jN¬~®ËæØÖÂ8UmËñaýÉ·L·I[f¿&@ѵ€]èÚ˜ªÏpnT¤³¬esڂͬßj¡‡¾w/«wpj¦k"´S„ž¸U<ãDp,CÜ…ä=&«Ëåé‹…LŸÀžê¼KPu%Y:!×ÞÃW·è¯îQ’¶ÏíUç& ÉBŠåGO¿e»¿CÁ.Ð_Ê¢Œã+iñ¡iWh\j~DåCX42@Y_¿â¤‹cÁæY:Ÿù2ø6%‚\+foœü ¡òÑ2Aï4n*ð¥ic:ר -õ³c"€¬àû.ʹt1iF’ vr'WÒ­õË›ðiT¹¨RÎÐI,vcBýµð×Ú_‡…"k6âM½+ÕÒ SOa ú¦Ë…ÓX»ViQBïŒB>]÷áÉXníÇŽœY7,%u¸_`Eña²í;µHîæ(”ýHÑŽTÃ{±[?ÌÈø*ä*8©; 8õ™6:X_ hŸH©Ð1W)®L)y4èÜçþcTåÉX¾ûËh^xE¡6šy}]4À1HÕ ¨F|ÉÁ'F;Þ˜jÃ…¢‘iüÜfIªã´½ä)­µZÆÚ™U5†ÊjÒž-ü ½˜G´¢—<‚u¡{'¤Ú£ôNOÈbeó 0Šã£`…•ôŒŠŸ*H¸ãi‹+–ÑuAr-¼¥°Çô»4Œv–ÁQÊ<…j†è—ͰzPQgsÞÝéŒ\Ç,—TV”ê5¬c¯†Ÿ­èiñ¬žušy]ÊrÛnJŽ£¿µ4–þÿðKO§“°ÌÄ/öM|zÚ  Â.ăŸ§¸ÖÚž'|ìoþÇ•¾ã]>ï`} ÉSÀá"æ6÷Bß~„f›`¬e#¢ÇR'‚L§Ël'ãÑÙgø ž2WƒÝ’7eï Éžg——¿&A8+ãÓ[CAÊ]B±äàT¥1xYŸÇÜ×M‘zi§Ž8 ɳûjHH0ŠÓè`ïý$±êéç¬ó‹ó߀ruò¡šþ3Óq×éKb ¦ô/Ó½“7™J¥ÿ¯Þ•ðˆ½íâF+ist ¦ö†Ý> § É-ÝJ c€’¤J­4îL)NF·ŠŠ)ð05 CåcÜo-ËÒcáQµp»³Dÿˆ"æh¹ÈƒV òƒI~î¡`OÅm¢fÇíRFnðâêNNÖsnì¾\ Lô†„±J¥à€£Fü‹çþ¡ßjV¹îÜú±5ïl¸swtpm-0.6.3/tests/data/tpm2state2b/tpm2-00.volatilestate000066400000000000000000000214341421141172300230150ustar00rootroot00000000000000 #"ÀdÂ3óƒÜ9ƒ®2h‡1ïªÌi§4”æþ»ÇÊh¯˜å¥<¼h¨X`ki ‡]D^ÿ|MVý±­^—„ó¤þÂÄÊAªMJ=ÐßRëwúÃóo©ÍW7á®OI-K$·ºÅîÁryMÇr?XìZ‚Ö!‚eõ|<F?ª¨[drŠêwpíÐS¼L¶ÿÅ\p˜G4D@M€yw )Õ{J·Ø`Ipo8xÀQ«ÔIHÄL+ TæåxL\{y2šè9[_E.ovÙçµÔÁC‘i ëCZæ»9Ĭ~פ.÷g*§êh¦+¿¦^ü»Ÿ4G@ûáâÒõdt‚ž´p*kB r`#Všš“«fÚ¶žDÓ¶bµã–®‰ÙoµfÖ ÷KRÉ„P#™ÊîL“7YCY3› y固â̵ÞOð,V€;âþÂIÊmNJ¨±XŒ×ɷݪ¡Ý>3wÉâÁö•fr–z“w›O´eÓ~kíg¶­övçÐá# žÝÅ›0'Ÿ‰ ‰{k(ìGt¿›’÷𚜋”ô@€’ÇV9X€ÙNºWÕCkÂtËSjö腓ȯ üt¼%Q¡¬ä…Û{r³ëÜxª­BÇ ÖqX;yÊvè}ê ¢$„‡÷6Aúú&OdUËS ­|:gƒ”ÒðûI‚ÿëIw@±B‘kÓãÔtØ—p‰Âh¿§f? Yq^Pqäÿ>ïéÞìhüï€)í¹1›Âkžå949˜@¥ŠÂD6LN”!ÝIkt}úø"M7S·œù1qz!‡Ôé: un=ݢħh»PKOÞì—$m²ûörÿS•˜¤Á<ñaÙGï­àwÝ ¡ÒýÓ“íBzqÒÉ=+ÆÖI>/ÁAä"*/TÁI§Ò/ŒmõKÚq‹¸o³n®ÆØJàíQnéÜXh#8Šœ*¨Ï Œm«zkcÁÍ ‚g ‡¢ß&°²ì¼Ö£škf¶‡W¢i¾”¯Ú Ü#¬0¸‰1eŽÓ_¶È€{4ö†BZœäoŽ}lÏÿv­X³6ó@F—Þ®çU €Ë0ßû>41.k¼m¾áÝöÓÞ2­?që%ƒƒH´XJXp8W;§ß£Áf[!@JGUæ~‘’ƒœ¥êÌMCãTa?ý8óŠð¥Ìï)wÚmðTT–R4$Ê#£}bÆî^;îðîò,!ýïà0×Á+ùÒz‘ŸÐçB6ƒêñ‡ÄØ/ás:xò‹Z¢L•èóâ»A¼`¦e×£Ó¥¬DÖnÓÉ{Œ[ÎSg …PÐK’hž!*³ËìÉļÜÄ2Îîçßçm-ÄïÄ·ígªD«áےͬ.:¾ÉÁëÆ'‰f¿uNokžv(htÙ „êÉôíôþp‡·³Îúmv%OXg+M­Ö~‰ ôiÕ´VÉ^ó³9ÜUü¤g›Y[p{°#Ÿ 4»±0õ÷íM‘òã°ÉóÑÈ»ÓO’ï»õšH¤sø5%j¿4àþÅáG%ñ78e6FáÃ…<¾¥—˧sð‰ÐÈB/?¨_–¹ürù¯c ;È©ýA¤¤Uú÷°‹ŒÈ8>o»ðÊ®xX}[2›p íBü¡Bzpçå zi€§É‚¿´º‹¬&J >ŽòtCˆÎŽŸk~ª(¨ÆÚäfÁšVºúëæVdJ:Õ©­¸Îú|å0ÂG¼—¨¢_¦N´k¶ê=ãžJ—Öp´·(I`¬†\*n÷B˜l@pédÇ"}7œ³ÐggÃ1…5_c⤩\9”ãØÊkun•qÿx'»«1ñLv)åìóðµúŸ•ŠL°!)}ñ¸0üm¶±ÃeΣOe_.sr:s¨;¥÷ðgžîMÚ³”¡,“¥–d–èÌü¬ÍSÓ„ÉPlÖÞí©yf1FÔ/E5ûod3_ÿ–É€™,WÛZÙ¨!»â7fÝÙüBFgf)û¾½œxKÏc߆¤åoaJAà6jª¬7ôH~TG-l“cvñÞÃ_·7,.Ý ©ûäç@N& <=›üÆ-C?é?‰¯OÕ_JÒ#J#~t G}¥êöÆ€Ìû Ã5ÕŸÖžë$Ë¢7kY7±"„åf|9]…¯Œµêw0ÔÓé†&Èd;±UðŽ|j®‰ÓÖ;|Ǥ.®øBóA¡ëŒ¨ !¢g Ï\Ü?Rtc¢_®$‹†ÄæL¦6צÿš#ÛmO,ë1·£íðokl$üÝÜ@h”Œõ•¥~2I™£:ÿgŠŠ«UÊ.:¦¶÷£ULÌÀÃ,~Ò<¾û¤“ ì€/3óÁ%·´(SäHʼnUöÛ€æˆL;Uƒia‘‡z-?jm°Ó¨}à ,t$}õ¾‹-ª¹4ˆáV® ÖâÍïÄž!Õd2Ï`S`nžDý÷Zr+ý´úÛáH²YÛל Í… Ï,zQ<¼ðÓK˜\ãÏfOQ·bƒ[· ØþûmF?#Ù(Bœ˜ÚµßG-ŽLpÚùc¥1€„YSëv¶ˆˆ>çR2úR*qƒý-…àd.fÎÞ´aÐêü=¯f7‰ ©nº2Lû\;øóZ)éý€I±C¤­²9Ž£0ÓˆØÄ”àÅÖøÖÆÁl¼ã¡kÐ)ý€hÄåù·ºag¿†¾@ÔeŽeÔË‚õJ$+ð<ý<áÑR'=ƒÂ‡y€÷¢ç+>ÏŠQ³ói8e!¡zØ€­Kºï¯XŽžûI…®ª :«íÖ™%«óžÁ?BÊ€P½‰Å”iš5S–¢ÕÃ?o±–¬.L_X욻фZ* ;Œ¤žëBÌ•¶ý94}@RD(JøÔ3× ªjâã'Œ¼®5L5j21S°óX>C-ãìÒVàƒÂú¿®iyæ·ß±6mÕ˜’G@lµòÿ³ƒ © O´–/Ì{ÁšinÞHJC–,¿Wþ(ÍŽŒð·Ê‹ ¸=L ÜnJˆ­dõGæC9§Ø1ÕwUÉÁE/—ö*´E9m:FÛ`=]hj.I)Ä7=÷Ù+zò°%Qì@¾¤MT#/ºä=¼á'êZ\Ûq™L ¯.ÒÀ 콌½Ã(7Ù5–Ñ5Jýd6Çô°ÔýÄó·ÿï "p7BQ(_à{ÛxîÑGA–ÿÎÓmåÏ`=M¤ñަºM5®ÐøSèá3<`›RœTp³K†Ár·n™w ÞÑOäXQ¬¦Ò)Ýç"¾Ç¯’RZ ìÔð]#-mìW”‹d\‹–h³ûÇ~õØùÞ1éYžA–=¸KG«÷¹nžÜcK‚Ã7"~%'Uœ,+4È4ç¾pzY+O=xa¬¸D¹*ȦPÒ.±D|êƒ (ïXÕ±Y×À; «&·6 3üI$78Ð=¹ß|ñ³â$>¤!Ê“ì«SU|òËÍxaÆÉoõ̇Œ˜Ž$Šnx$5mé:—æÆê/o[re×ÉîIæ‰x#–`Ò Õó‰ §×õ“b²ýÝ„÷•Ù‹ç+yغ8œùªV J·Žù„!°D{?ž¤ÍŠ‹…&kç™8NÛí'…¶lÀ•е¿e#y›ÐÙé±T$KHT"?.þ:12{®À:¢™¯âëQQÝÃf¿êc‡ûrAnG0‚|¦yœ¯ wEŽ·R±²öÞ–tXÔ°_–IŽE ŠªÙ& úÌe”Ò‘DR0®d7xQ 2œA¿ZÂVÓÙÎDÝýx_”YD E‡&ìä\l¸ðÖé”؆Æö®»@c¥BÉàQL‘×ßýì¬7ø%濾Mèµï‚ oIÒH͹*±c˜G{ŒÆÆ›0a Ö[\“Ï9Óëý[X¤~šþ6¹€|Ò¨qâ)ËžñœÌµ™ »ãKòÚñ…HPÚg¦Ÿ µ|6‘ÛÑ F|Q]©§õÃ3¯cìo4GÙÞOPfµ=õ¦”ÆFt»ØíÕÆJ¦´R‰’ ª¦Ž.ƒjðó˜ìhàìZηøŠ,käÉuþË:}ÀÌ©Àžð›Fí_ q»khï@-*c=ö™Ì²ƒq™óm—Úï"y6x@Ï›õ€¹ˆÀÝë§^§¥m1ýXº|oáªê µU+„–Ïþò¿… ‘îEIð›øœëÒ+AÃ|¼ý=Q0ýp µoØf*=Hˆ]³¯Þ+o;øøÐ]üµxB’[ˆ²@ޏBXLíð ]¬f³{ªv àq7?¯µ{'oâ,9[’%& þ6PÈ4']csDZSsô+S³567A^Œ­¹a¡uL‡ÃÛ´3@|Z¯ñn§¾;~ ¨…‘Ÿ)8û0î¦È‚ÉîÝì2nAi ²¶BAñ®äüi¢ƒNÔ¢°–$ö,Nœç‚Bna™Ú°¦W‹ë’ÜRó௸”Û¡g¬þ‘y‡çÔsàm}IMÈ6÷ÐgÙ;P•Š•Ðý2rð]×3lSè\w›$]Þj' £GZ‚Ûoˆ§“’«c_Å— õKjάNC'0®¤£áûÔçwW‹li :xW ¾*åz ]ûGèpbZù˜Sä EU(¼6œÞ „M_5i&yŠ€-þ%mh¡LÊOÃï·`h)GÃÅα€Õþö=ŠG™³cÉ8Q€£IŠ–Ëb_ä4È|Nõ —Q*ù;ñ¯,¼6Tøª—à ÔÞb?c_“‡X$­“W{¹m—Èà Ö%šòøxVê°VÉBRÇeh·›2¨£U¹úÎ>;Ï{¡þ°—g䈙‡ÉÇU'Çnb4±î•kIä.³hã‡l³"}Œ ¼K!¹×ü–¸Á·¾A/Ñ‘- ű¶©†âÕQ¾=;dà$Úz.«iï7Ï]&Â×W+–7)£äP+¿ÈM·ˆµ·÷ªw#”õúõð¸V4²ùDM)ž0°îêù¾oQ™`açOÚ Î\Vg P¸×ôˇ {¼6^à~qg‹L?A—ÁÝü˜5ˆhlskº¡<¼‹= ¨¨Å#d?O”觤v§zÍÒ*Ï’A¡½›ËêÊ’Êæ G^ý뎙½{âÂ'÷.h÷Ç»&Óu'Ä`ŠÌVH¶ÇF¨Í)®R¨RñOîÎCô"Y|ñ±ãrS‹7üÜ.ží8”³Ý*ºE4¢Bðjm¢e¥œüÍϾ7€ø´ùž,ñý$=Š&}ГB#b§ý-ÿ茅»ãÎWÕ:#Oo(;¶‹YC‡#c€„´¨ú¼{Á6iR;Ïz×ÕÕv»?ƒ ^i¯ˆ•V„gu‰fãÇõ’žá8%‘iátE\Q@š§Sƒì­À”ñŒx"IÜKUÖº@”ûO¡q†œJê¯6“ð f~߸[_é%Nƒ›l‡hj‹¡—íMk'OׯB Án…­«µ·à€MìæáüýÕ-Ôew¿À‰пhNúî‘ÆðOÛy\²j¨WwÇ%ÆÒ­¯(Ϋ-*)}UÆ¿t=§ˆÒ’¨?$ ºòÝ…ôîêWUTYdªfoÈ‚¥‚ª˜m+ 9uŽëå¨ðÆ’ê…$/.Ô§ñÿ|®‹C EƒHúóF/¿ ¾ºX#æQˆ0LsYk1Þ+Œ'Åäò¥hy°‰çÞ;º¥Ìµçø x?“m¿¸úVLn³Íé‰ïPÖëÃF#UÊÇmJ’Ÿ¡<Ÿ£(Ë}HUíÞæapbðÜ Zl†¿Ò“ŸÙóíDó º[t™´°¥µµyxf$· ’þ½]ò}'D¦ÀóC5üXBw8ù¼®1ÙL 0“~÷ú²šészoW³¸ý‰6“xb,:ùD†¢‚Òd ˆTf\Ù| l‡¾ð¬Q®·/yîå³ü7+ŠªNG`NÊYD—³ :àÿD$Bܧ °F9H½t^Ö7h?²õ3AU¶ +B²â5 w.¼9dÔ õÕѺ ªf,ãá}…ß8Ø· œéãHÞ ½Çƨ™,y÷£`—ø‘š8ôœ) ¾g!^ù×TU^qe·áÛ{ÏåŠm Ša”Cƒ¤€^o‰ç:4n“Ê—êùïªw¸Ê§~Ã@NŽvÃTÄ(Ñ'_>mëX:#ñ÷!Æê¿»u¥|Ö¢Á!lÕÅòÉ5RÓ¾n‹£ç2EÝ™û“Ÿê XÒŘ‘ÞÐ ÉØ·ÜæÑ´rö\‹X6kc?&‰ÎËâá%1‹¾Ë1$Pó¬1%H$JVÁŒ]¸¼éº ç#pÉ4‚ÜŒ6ÂõqǼÛ)³/Ä?Cž°¸‡LÞ0jæÃ´úÉ pôĪÿµêpˆY6Jt·qKøö'¼ËR5ëH¶à ýk˜-¤ñSt›ëªm:Ûn ÷¸ 㹪J½`æ=Ó„]Ä´,ž³Xœ~ͨy‰‰0=Gù9ˆÿÂ)öhnà5y•гb§Ô?Š«+eÜ`繞§g•ª¾ fÆüÓDñ/<×í OM|âÝáãsþÉ¿ýŽØob®š7„¯Wû$š%Ä_+…ã‡FƒÚkð¾æëalY"nm\Üðhþ@KvF³•=&J1j†ðü|Ágz5$ZÛ5Y½’ƈÞ`”Ò§®Å¿O¾Óí{%6%“3ã)Ää^©@¤tŒ¢AŸlG Ó­eºƒàÝŽŸ‘«=ÿ†1Ü#ú,Å¥bͮǢNÀÓsÓ­ü„¯ûݤ•;¯? Œ8ªälÙh/Àí¿Î[YõºÍ1‘¡ê ê±`è%Ë]ä§= Ó`ðÍfämÇ0»%\ÊLVzNµÞD¦ÔÁ‰¤ˆE0q+Må£NÔö FN3æV™ÂÙO¡ŸM€Æ—Öþõzx® [À'J+R'Ô9•²ù¶ÅäPµ‹ÇÔÃsñUáôRysq¶ÒÇb€P*ÅnM iK¦áí…®1ãEqß·Ç®KÄ;šVõA¯)CtÀ@Öûo_0evÕ 4ÿªH„?Ñpú7YÅSâî·ƒ  èÀÓÆVÏp-c--^bwKÊnèJÛZšŽï®ZsQó23‘òy\›.ÿ¡E8d¨¼1·#—Þ)‹áZ3ÆŽ>v¤äóñ]îᯤÅèd—ÊŠ;Ò³¢¿N”aø³‡³àx3ÐßV¼ù¼ËËJ?Z¡é|>ý9J+Ú%ÓùpJ±503{ÞHÖBÚÐ/‘*eå}U2½H-` E/m–r´íý&Ê'8ö.1Wúå0IKR±îàÇmÄ¿Y`Qìãm?X!ì”Ý=_µÿݪä»X™„Äa¿Ï˜ü‹L|?œ Öÿ‡Z÷5™‘χfçac¦Ž«n^ðaD|rsUØ‘üiH-Œ)%cÉIªˆqëÕ•—*Ó QØŽ—›=Ÿ6¨f˜Ñý¾+@;S sMY ñ_ß~žÁÚY­ο‡2;™“0Î$ñ/=Iu‰ÎcæWÇádÁä&=Ô‚/,éHv$È…Ô«Ýï³Êë[L¢ÆðAŒ  ^ .5SΉÝÓ¿®!Ÿ…—;ʧ6ìoäVQšVô.9& &­½&”Ô’#÷öŒ÷‰¬%rõY)ݱ(¹ß Á¬h8»8ïþ*ç ³bzm‘›ÕžYÝÿ¹ß,dr :¦Myÿu eÜ=‘Ѵ߯«GžL8|Ù…0UBÛsßTóág‹bnìÚûÞBóD"=Î9ÿ£•fºy™×h¼Þä;w¾‚æ.çÒ‡_¹ÅT©ÐÒý Q'±2Ó®uo&&ÒgÈéÞÙ°´ ¬€Dl}Z?â(½ÀTe33"§.ºÂgª¢“àgO2ð\~ìb©·Œ!d%ojY!¹T¤zkNñ^Øã‹î-ßðC!rÎRã¢ä«ÇÕ½>À¥hÍ\6/ª›QOÆDÿVKÖfúæ­"„ÔèH0n§›Àªí±»áTÌÌ}‡OÊÊéÀ²U i8wÒ7õ~dÚÙPïų»ÃØÁÐÞbbÅŠá²Ý ޶îbAÿ+|¡GBRD0uÉ¡¸ÿFÕ¤wz':Œ D¶ ®/ÏzGÇÛÑåHq¦<‰À¤¸ÍSÕÐ&2¤1»}SFþ«p&hdHello TPM2z&hnHello TPM2 O"Ãê˜%G&Z `dnnn˜%G&Z `nnnn%G&Z "hxnnnxHello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%G&Z "h‚nnn‚Hello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$%G&Z "hŒnnnŒHello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.%G&Z "h–nnn–Hello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8%G&Z "h nnn Hello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿB%G&Z "hªnnnªHello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿL%G&Z "h´nnn´Hello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿV %G&Z "h¾nnn¾Hello TPM2ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ %G&Z "nnnpþš9tÀ8u¾s¯ r¼‹tèdÞ®;ÉU8oöƒÖ§”^ ¡n&:—å2<‡§xš¥b7AŒ'%‘lg-†‡%°Ê‡‘D½ˆ>$zq Ë2õMÔc¿]åÄcã»ð^_Æù§‚CZ&ÚÅg_üyƒI…Ä;W¢¡¬ÔjZà, ïùà5„›‚ÏFuldâo TÛÓ|k÷!\ÖýÍW†Ã”)Ü­—‰?–];½hý s&ÐŽã|wܱÛkQ^Ï€lTæ%Îûý;‘ǵHjBW³º½ö—hgU#’%Ðæ¾'åxJ‰l…{D‹¢¯nB¡Êø%ùú"ü‚ž·i@´OñÏ €æž¨Â+‡nP³”_â}bàÙÚ÷³Œ.Þ¨õA¹T)–Ó»V–¦H>¾êULåþЋ6’i}Nb*(Æ/c»Ídºó̰¾ì$ž“I2hyU¾TBMf–ÞÉmí´-|;TëCÁzë¢Å:©,û  šçÑÖ²^K®ñ?—?Tê²/ç6«€ÓKFØÏ^j%µaA'“Öꦣ,ÎEÈVöŒÇQe„ÄutPç‰0úèRa]T bh_ÍxhöãP=6¼¸3Y†oÏah¤ïÄ™4¨§m~7ÏÁç³j“ýÁ‘¦ñ·` ;Æò? µ hã–kÜR´:XÑL Q/ç6«€Ê-Û‚¨îõ?žÀñHhzý³-XwRyFqen[ÜéÖh¿?ÓÊïN}í‡ö6Ø#@9Ez”’×ø¡ Îȳs˜¨U£P€½Ófå’%[xˆx›®ºÄ’A¦ëü«¤—Uh°í;nØcàf¾ä¯tôŠx†Ä)H€t[î¤o[/ç6«€³¦¡Ü5§¿ÛÖö•Ï)òæùpÖ«ON‰~H\"±ã¦Gà›½¥.Xâ¹x,EOö&›¥‰ö㌖¾É¤µ¸·ý¨½}L¾¹k€Ñ3¼ ~mn£ARýBù-M/ª1*nOú!<¦xñVqéÝ Ù cÃ#!…~{4@Ë¿•"/ç6«€ré ¯â°£ ´çPãrj‹%¸¨‹ƒ o1]@ß@)˜-Pö¾Ðlô*bêc)Þä“}î ©¸†—2U@1}Õ‰žÍŠŽÚÉÊÍÓ0ï¬^&ötFOЂ•x_ëŠhuµ hÊ›Ø`û9]Yp#¥&û‹Ä¼7r#ÕtJ·ª8ú¡è" þœ7Ê^û ˜ËXƒ—(à“Ø/¦µùÖÇEzß=y" ÊÃOsZSÓ6B yåR-X:ƒD4åSY¦uºÿ(1«6G#swtpm-0.6.3/tests/data/tpm2state3b/000077500000000000000000000000001421141172300171115ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state3b/h02000000.bin000066400000000000000000000002601421141172300206320ustar00rootroot00000000000000md⛜¯õûŒ€ÄÔH¤o›Ö®êíñbKœoàרg è%ƒd¹¸Rv®\õ|0úá¸ý¡Ö(HO–:£VÊ¢dCü~6œº—PŠ% €5tH/ñ4d¥Ôl©v ê³ãq¬ÿ\ù®ú×’Í—´v}0Odôp#pÕç M`ì²c£¢ìVI(À>›ËÐúx?ÔR¸LÊÕYæn6?ÞÌQý³2³“ZÀªWtúswtpm-0.6.3/tests/data/tpm2state3b/h81000000.bin000066400000000000000000000000421421141172300206370ustar00rootroot00000000000000 >u‰isçû[ÉÆE GØAŒ¾½Jì ½-' ÿ2swtpm-0.6.3/tests/data/tpm2state3b/tpm2-00.permall000066400000000000000000000123201421141172300215640ustar00rootroot00000000000000«6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@Ï·J ——SkŸV)jÓ¦tãB¥ß@P=\¦ì¼û„—âŸ?õÜLyYriÀ"rrbcá×òª1¿F‚Ï“@–áä>¼Y™F‘ÜÒ‹K0CôÔTÛŸÎ"ooÀRóÂuÍGVŽEð_²7à,`:Ú®]4öÚ®` Ã*NŠˆã@GËÉW%Þæ&‚$TZ£*¥³D›!ça9º sš}í(ÖþgXA9þ÷ÿö·"råî‘÷ŠKjífL ôÿ{¸ÝX¬ü@W]#Õ¡ésb÷lþö¸ÊAÊÊ"¤T8)t+°O ’c–pŽ$Š:¸o/SaJÎÓ r«*ª ¥14†@Φ5;ÉÚ ³rÒEÓ~]+Vö¸ÔBòä‚<åôulPAbÐ¥ôcÖ¶›ø€¶skEÅóúy£m• @èY* Àd°ÆT£DÌ"Þ«ý1¾ÈÐÒWßLÅù£ŒPvè¨È&y‰ídTN>uçʃ˜oÈ?»Yc kæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èè€ (Vex‡¬oè>¡~GBRD0ÞÝêUY°¹ÿ×¾;Dzx´f"ˆ*.ð’ŽÏ`êjQ„ÜÑC¤R&gä,\"$‰ä¬#2@fQ–)KÙQaau»kg$av|@ô%d¡q°«Q±x¥ì \À4Ì»Sæ&OšÄ7Ö>µ {oyeêâŒd@‘TZŸjyz {‚÷…?Huʾ@Ù)-BõèÉ?úOÆÛ‚ëÍò©uUrÛK/þàð†xëp¯=Àˆã¹„@\@ƒª2®à}9sæˆñ Ö‘žÙæM©YÌ[/é?«¹#hØ+{Ò(MŒþPJ‚xÄŠ)_štŠ6ô¾bP²¼h/c>ƒ_äåcƒ_½À2ŒÚÿ¡åj8„ŸãÌBÏB$'\Ê %'­P/¹ðBéŠ@’´k ®µÄ4/ÇFV‰hUÜõÈFIÅGýÉyÑ,´LõÎŽ/%8ò(Ò_²ÉÞŸÞ6èibÿxç·DM߆{±˜Þ©hÍ —kvוf´6I†G5ätnW·8’º9mröÇÒl(Âõ…îûßã*ÇÎ&Jüöx˜NÝâÙ ¾~ÿÁåŸm(gùzhIO ^ˆ’ëÀ_´Å'êßýî·ÎƒŽ×“¶”}³ñöÅRâ×€ùQò.žŠ!Q£¥5dQ¦øªnã·éµ:v1Ó®X£QÐ\ŠÔ+¦cY¨P¸ð¦Tzrå‘èg†îÚÆ\Õt×ÃüÝÕepˆ»ßRGE‡Í™¦Ò–ép#´ °G¯Æª½Á•ü¨ðW-Ã{øvÏûâ¹-?Tê²/ç6«€bð®—Tÿ¡ë€Â—„êyÎ,7º•“>P— )â¶eD‚ȧN+šE®1fNñÃ{~ u[Æ læËúo< 7Ö —¢JœØlí'£ÍÒzX³ec;±ðvO¸†Ôû½'Áê”u¨$¸ ª‘fw/& '`ø¬Ý^%…àÇz·/ç6«€åYü¬Ø`8#ú_©fï0nY&TW”šý8r+Œ»-OtÄõÿì©wW§õ MãCÞ ?>ÄÔõ‡&o¡ ŠH¨ÝÅw£lQ"–;ÂíLsw_m’H¶X¼È/M³{ÆVÑÌÅèZ”¬CÏY¿c™ÇS°Íì~‚˜</ç6«€ìäÔîcÚ¯€Êú|°ÝUÔé €éÅ@?˜P\âŒÃf:¶q6p$–‚.¤ŸXó„†Kßkئ’ðÏÌiêEÁÑ‘ݧv uŸlfruŸUºìºýŸ€ì!o§ÉbV:e¼û…Nok¸Ÿ}pêçAçRD ´Î…¦p•ü€€9÷/ç6«€5x•v@¦>AL°_¶SÐaÕÀÖºÏ~‚<áâ„|8(t ž¼î”TòC¶ãÙ†M«ÆIÀÇ ³^t§–+ ²y Öˆ6öVõñ‰c*[ö(K›¾)•ÉÎSâIæAMúZ‹J8=ÕUàà^¿jÍWNëE^a°Ô" €`Aêžj]Z‚x…i²­©‡¶ÿ«q ê†V‰ë{B‚" >u‰isçû[ÉÆE GØAŒ¾½Jì ½-' ÿ2«6G#swtpm-0.6.3/tests/data/tpm2state3b/tpm2-00.volatilestate000066400000000000000000000232471421141172300230220ustar00rootroot00000000000000Ecx‰@@@eb dluohs eulav euqinu laer A .eulav euqinu a yllaer ton si sihTVex‡oè>¡~GBRD0ÞÝêUY°¹ÿ×¾;Dzx´f"ˆ*.ð’ŽÏ`êjQ„ÜÑC¤R&gä,\"$‰ä˜‰vgsrê¼@   kè.¯#2@fQ–)KÙQaau»kg$av|@ô%d¡q°«Q±x¥ì \À4Ì»Sæ&OšÄ7Ö>µ {oyeêâŒd@‘TZŸjyz {‚÷…?Huʾ@Ù)-BõèÉ?úOÆÛ‚ëÍò©uUrÛK/þàð†xëp¯=Àˆã¹„@\@ƒª2®à}9sæˆñ Ö‘žÙæu‰isçû[ÉÆE GØAŒ¾½Jì ½-' ÿ26d®¼6d®¼A c‰:&Âu0c‰:&×É@Ï·J ——SkŸV)jÓ¦tãB¥ß@P=\¦ì¼û„—âŸ?õÜLyYriÀ"rrbcá×òª1¿F‚Ï“@–áä>¼Y™F‘ÜÒ‹K0CôÔTÛŸÎ"ooÀRóÂuÍGVŽEð_²7à,`:Ú®]4öÚ®` Ã*NŠˆã@GËÉW%Þæ&‚$TZ£*¥³D›!ça9º sš}í(ÖþgXA9þ÷ÿö·"råî‘÷ŠKjífL ôÿ{¸ÝX¬üEcx‰vô×¾¾,#T$®·Ãç*­1{swtpm-0.6.3/tests/data/tpm2state3c/000077500000000000000000000000001421141172300171125ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state3c/tpm2-00.permall000066400000000000000000000100761421141172300215730ustar00rootroot00000000000000«6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@¶¸«)ïPæFœŠ©¨{äÜ{ýr¦6ߣ™H‹2g/þ2¢E7¤KmÎHaº໢¤”¾:E»¢[ÙfL¨¨@²¢fþuïÄŒ{LsÊ\‰Æ•–‡åMždœVzÆIŒ§ÁgJCF“˜Ñy5jöKˆ``…B矋Û,ÄËøBS@ÜP]ìÐÅfLÆáo:ÅwùÊOoî²3°˜b¤²'ç2¬hN¬3¦ö›ã~AZ«?a ýÏ'“2Äßòza@„DúB‡Må‚%3_Ò,h÷w‰»žÅd'é¯?`|±w)‡•7l kT¸r¬™¬á´Ÿ× i«'`0RþSâõݨ@Wˆþ€ö*÷ì29•›²*Õ²dY’–)c‘ ®†úv‡’”)Í' Ã墆]¢ÍH0ÔÔxM­°Æ‹¼;W*@ÚXB®¿˜¹h±RÇ­9WÖ’ó:½£-6`úRjƒªÉ¤îÌO$Ù^TÅñÞat. – 8ý„Ñ©]È9€¾kæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èè€ (Vex‡Ûoè>¡GBRD0IhpOþ 98áMÖ(m“\_šŒÖÖ²$óâðdDfL¼¡d`×%·f–Àµ¸h?×Û#2@éºîI2¹÷ÊêŒa`š6ÎömHâêá9:•ÈÈ/M Ncc—§ã|Л ›kQ½B<}ª¬lœ<µÆdW['}Û@ZöuÔ ¬“¾`ëD© †ÞÙ™™,uĬµ&÷^Y*Uºs:Rü×ÛSÛn ±ZAjYÁ¨‡G»‘-·í­Ä@\@y·µ›/xÁéÓù‚dNÇQ:ó(Ò)¤ì/“Yr¿~§v<ÌàºË4QÓ6~ð7@Œmq§¡qÉ5¢Aÿ>Hâ÷˜‰vgsrê¼@   kè.¯SFþ« O"Ãìü«6G#swtpm-0.6.3/tests/data/tpm2state3c/tpm2-00.volatilestate000066400000000000000000000244741421141172300230260ustar00rootroot00000000000000Ecx‰@½@@eb dluohs eulav euqinu laer A .eulav euqinu a yllaer ton si sihTVex‡½oè>¡GBRD0IhpOþ 98áMÖ(m“\_šŒÖÖ²$óâðdDfL¼¡d`×%·f–Àµ¸h?ט‰vgsrê¼@   kè.¯#2@éºîI2¹÷ÊêŒa`š6ÎömHâêá9:•ÈÈ/M Ncc—§ã|Л ›kQ½B<}ª¬lœ<µÆdW['}Û@ZöuÔ ¬“¾`ëD© †ÞÙ™™,uĬµ&÷^Y*Uºs:Rü×ÛSÛn ±ZAjYÁ¨‡G»‘-·í­Ä@\@y·µ›/xÁéÓù‚dNÇQ:ó(Ò)¤ì/“Yr¿~§v<ÌàºË4QÓ6~ð7@Œmq§¡qÉ5¢Aÿ>Hâ÷;@ €ÿÿÿÿÿÿã!Cî•,Ñ` $›üv‰†õ“àìô“Œ $›Êþš9tà(u¾s¯ r€Cº`^ôÈÆv-õyf.Ï{0ÖÐ 4ävÓ_âõ„7Ûµo”ß Zmm7Ó{‹솅¥gNù˜¾O|é¾âÁ¢ßþx½HÂûþzÙJNs½ã× Ê•´ÊT2¶@ÏâèÑN¨¯ÅÂkï x¨o¢yJýÁÍëŽ_MFÿ-;ñ›Î¡ì¸WÙ)PI‚ûŒWØŸÕ–?zÏ~~³-V2çP  £B<3KNüZõ°¢gmŸ²U䎼Ó¼-f®#R~Áµ>Üh+Ç×yä¹?näK ƒì><ø‰’ØŒ~\ÑI¬€ÆR]c¾ânØ‹Æ&ýqe­fWõ¥ ú}Çx¦ž„ˆƒbÅÙ¿A8"‹¢YǨÌa$9MM™g€èîG~ÊÉÀ˜ßB 0’Àh¸p³ÀªÁq…XßT—î­û¢A‘ŠksÏô¬“#—rü¸oÛ×Ç}çíF‡…ò>ØêeŸãŽéã ÞûñX ¸§yÚ40žåŠ…I–O5ü_-‰'ºsº·Ýor¹÷,™É¿‡p7?Tê²/ç6«€k$TyvühQ×ð¶ƒêë€èí[( Šf°ø;K¤–ûZ3úâ/‚|¦ýB›Ê:³-äË4Ô‘µ÷ü= îcå¡ 0õb7!àkçRâzã^¿?¨!p¯ûÅrÞ ªA¹sÉlàS ‚Êï ¾•î¯Áàš¤ÌÖÊ/ç6«€à› „*™¾AîɘçäX%ƒ àÍ¡sƒEC4œR&Ùñ\ß0oùûnï.ª¤…&Ï‘q@Ë;]1¡nÓAÍ>ÄW\ü` >±Ø-E‹b¥J ¢Qö×ê¤w÷NC‰1Z#èèǵ¶ ®ËËŸ|Ť´'žãÀRŸ­`˜†/ç6«€gLmCr¼á ©³ /Ê×E¬žPÏ›€ßk2³;pQô‰DÍ;ú¢›2™Oàé;uvEݰ>Aëö³€jWÈES-D˜cš>P¶œòQÀööáF•åëM ¦li¹Y°MIé^6 ™½¬¶*[$QcøÑ«.Tá /ç6«€ Ö²(»ìªRŒÔ±‚¾¾Üy*k+à=.£0ûOÌØâi,Tt4»gØ0‚$ÕÌáÓÿìô©º+ŸfcȮǖ6¨4õc+óùtq¿o8ÒD)‘c——¤:Õí(jL'ç× c䀌´ùU§ WNÒ+ç¤QD…¯©¿" Óý¨5®ÙÜiè‘Ûr1¡?ˆÁë3®`åþŽ„Ü" ñ[vÎT¾g²«§k¦ìt˜)¬v.©›ERÔ¹²Øþš9t€u¾s¯ ` ï^™Qa&;é((Ÿs½Cš‰gàãårÐ&uSi!ã8âè _ߨEI8u$$gÌ"T”üÂ.E¹(´ZxÜW¡`ñ¿ ¡6X#øÀ¶ ¡DÁÚ)W-4ìéK…iíÜf”ˆ1æ]?Tê²/ç6«/ç6«/ç6«/ç6«" ?ŠMì‹èx‰ÁÊ7HóoRf®shRO'#°X~Œ¬R" By@ph|ãÁ„ª[sƒ?.—ü[ü’X±×þš9t@¸tþ8V(x¢ 4IKn YÐØ=Å´õ‚ýœÕ¿Âòˆ²Ø»ÇËF cVÁX±@123 @Iýj¤œêUý†u qh°µÙ5±€:^ÈÔmº@\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ 0 @%6d®¼6d®¼6d®¼A c‰-¥N½u0c‰-¥dÉ@¶¸«)ïPæFœŠ©¨{äÜ{ýr¦6ߣ™H‹2g/þ2¢E7¤KmÎHaº໢¤”¾:E»¢[ÙfL¨¨@²¢fþuïÄŒ{LsÊ\‰Æ•–‡åMždœVzÆIŒ§ÁgJCF“˜Ñy5jöKˆ``…B矋Û,ÄËøBS@ÜP]ìÐÅfLÆáo:ÅwùÊOoî²3°˜b¤²'ç2¬hN¬3¦ö›ã~AZ«?a ýÏ'“2ÄßòzaEcx‰áÇn™R; “¬¸žFuߤŠswtpm-0.6.3/tests/data/tpm2state3d/000077500000000000000000000000001421141172300171135ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state3d/signature2.bin000066400000000000000000000004061421141172300216700ustar00rootroot00000000000000 Ò„Ø]y)Dž%çoú·"å5-ê/A^Ø]¬¼66«Ž•jÝcs3ÜŒmÆ2ž¼Ê,?Áø³×pÔ_¥éËžÔŽ¥. †1i—}óØØ ×k¶aC0d',¨}*hÅÓAˆRº´„%ÇCEç§hez‰…$¢ç}4®ÑÔ8¡ÞHŸd`ܪz ‡zï"ŠÑ§ÝHS2*#áW©ëq¼+-E­D`ä•p†UÉ,!×Ô^§”¤~¯„aV„ת—é !œ@Od»ôQÌ—L/ý‚O;*…§ÂD‹CàÄš>œáAúœØHaÑéÝ^¬w:(‡X¦4êÓ—swtpm-0.6.3/tests/data/tpm2state3d/tpm2-00.permall000066400000000000000000000022351421141172300215720ustar00rootroot00000000000000 «6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@͹f›M‰ò-u€¦šÑŸž©5³©Á«¶„v9pbº14C°Ôbiº¬1¢¡÷ÀR…ÙŸ¦G»ìÆUî5ØY ó^@& ry¿mžõR¾F?óÒ…LôùëAæCèXqG° eLö8pz¡LËú£ÙO>k‡}ðXë6dJ ô4IU@$ŸÆ®ð¯¸”r®w{¶F¦æçSP6زŠ&âºRšêÕ#ZZÏñÙZÄ“®KÎãçŠIŽã±ôéÐ8÷S^@ V/ÚòÍq6‚Œ|Ë&y{zá‚¢§íñ¶ð„“¤Ó/Õ$ ÓúhåöHKŽ{¤¢ôâÄ„µræh F¡@GìIw—$µÀ¶óŠ:o7ʔԙ=-SñE5¸3åØC–‘DÑ@³neX%ÓSÕÛ5éW\-|¡£š³‹Ô½oH@·ç5G·Ò P|CyžŠÚûþnäUÛVwÙ¬ ¶%D'¦¨vxÊJÞﺄî70÷§Î›€Ç^oÌ’€Ô »kæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èè€ 66ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿVex‡˜oè>¡GBRD0 îߘ|"AoË#·ê.Ué—@”_Xò‚w‡è‘}2Ý´”v“Âuñø˜ (ƒK¡˜SFþ« O"Ãê«6G#swtpm-0.6.3/tests/data/tpm2state3d/tpm2-00.volatilestate000066400000000000000000000243421421141172300230210ustar00rootroot00000000000000 (â(ÒEcx‰@p@@eb dluohs eulav euqinu laer A .eulav euqinu a yllaer ton si sihTVex‡poè>¡GBRD0 îߘ|"AoË#·ê.Ué—@”_Xò‚w‡è‘}2Ý´”v“Âuñø˜ (ƒK¡˜‰vgsrê¼@   kè.¯#2@54+O^ y!¡ïTAኮŒÐRXcKD Á¶Â×5L_Ì–»;äO£W °PßÏ ѳ"uD×}´2DЭ@ ÅêæABb[¿hmN‘1,Ù 9Ëú':·Y/Gê:G”¼¹ë\ýaI]]Î$/NØè”¾ýé€.’éáv@\@Ex'à—?ÙÍÌHþ›²ùÑëçH›@>_#X¿]e[‹ÓKF§Õ-åå0Z¹D6*Þ²Œ“œ­€ˆq;@ €ÿÿÿÿÿÿ=þš9tÀ(u¾s¯ rÓQÍøÕ"ƒ£³äcӨ߬§-Hë|@»lÒËÙ–¬vôCÔ)H¡ªûŒwÆ{ÞXX~þêÞÝëÀÛƒÌ=ñÏî2ö§ç_Ê4ˆ‡EW¹¦´pg Ûêyüª¹äc‘;¸ZÖŽ™ ÓMÎ!T§„¥TéäV }æ´%Ç\ØOÔ+ žtœ.M=¢²L؃2™Î!™ÉÀ'“ÖŽ§,¶¥µÍ}”…LrÜî¹&¯ÌßM¹3y¿K0žÙ>ïãííA‰ý…¾XêÇׯg;|Ÿäüº&°*9' mÿ/0£QXœrRÀ¯/GJ…œ%1³Dà1gÂÈé«Çß €é·ETù£°¥RÞ¿Þoa!WM‚Lçà Sî󉞑¦BŒÛ ü[ç¾Ø õœÈ®0¸&´xýýç´²w™ÍQÀé¯qFËsYã}Mÿmౄy´T&ŠM_ÖO¹7 ì]Öž|‡YF¯£"³· ¹+z0 Ó?Tê²/ç6«€¸aˆ`Ác|EYMºË _¦ÕÙCâe]øš:´Ùò–¯ÚtóJØÓ'îÀ›âŒÁ%hzMFœbQ>W$51¬øÞ­*M ÄtÉûË[6‡ˆfûò‚‘;É ¸‚áJíL " âç+µà\Ä×y]Ö.¬ŸòÏ>ì´Àv‡ÌB K" ²ú¥Y jŽýòpDYO]-%T³œÔëj:Â÷D6Y2–þš9t€)u¾s¯ @ ÎjkWì#ò½¯,×§×…õ¯°ŽÃe¸Ì2q9r“ǪÜrÔÁ–nuFÖý.ÀÛ§ÖésP’ÅRôýÿpÎC¦¤[]ñe®¹1Ý#Eù 440iœ'¿®uò—#òJŒfêcHЉ€ÄRrâ…攚 :®/c;â®øWÌÕ­œw]¹©Ôz›%^Ö2ô¹~å–˜S¦Ár r&3ž§wêŠÒ¬[£fì vå«lŸ3ëhíB´©9Ýd-Ø/¬Íß ™¦%Ûá¤ô#7ü,²_;±†´žËND¾H*ÆÐ)ãWâãV¹v¿^"ΔÄ·™<8À7A?Tê²/ç6«/ç6«/ç6«/ç6«" ÍXs“ `*DjwaWoÉÐÝz­ O£3Ï'" ÍXs“ `*DjwaWoÉÐÝz­ O£3Ï'þš9té_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ 0 @%6d®¼6d®¼6d®¼A ppu0wßSì@͹f›M‰ò-u€¦šÑŸž©5³©Á«¶„v9pbº14C°Ôbiº¬1¢¡÷ÀR…ÙŸ¦G»ìÆUî5ØY ó^@& ry¿mžõR¾F?óÒ…LôùëAæCèXqG° eLö8pz¡LËú£ÙO>k‡}ðXë6dJ ô4IU@$ŸÆ®ð¯¸”r®w{¶F¦æçSP6زŠ&âºRšêÕ#ZZÏñÙZÄ“®KÎãçŠIŽã±ôéÐ8÷S^#Â;ÿÂ;þýpEcx‰Üƒè Ü£ÁŽõÜ¥+LE¥ËæB3swtpm-0.6.3/tests/data/tpm2state4/000077500000000000000000000000001421141172300167505ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state4/tpm2-00.permall000066400000000000000000000022431421141172300214260ustar00rootroot00000000000000 £“«6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@¬¿')9'/rg–"î˜ÎöOUƒgòé‚ýUº1œ~¢ÍìW A²P%3á,2‰d«J(åw*¹ç4ÂÔD¹h¤…@£Zdq52eâYcPf²n¬·hÃÁ_ç gùNŠÅ`µÊ®S˜ÆÎë¼ÿ•çäϺ#ÉÀÌQ ƒªn&@êÜ9l;ihk¤ÿøE>ãNÃÀ÷ֆƤë)õ9­iw'>ì–ö¸¬±r~‘æô¡„ñÚ‚¤¥CY!ŸÐƒ^@‰2È·/&¨"x1{¼ûÕ?ˆûí•Jìž’l®ʇ'W‘|\¾úõÏÎɨރº!Ãl÷`·F?ØCbnL@:Ž4×a‰ÆQfš·Ñ?ëvqˆ˜¿& t>ú´AÒ¯ 1Á¡Ý‹·Uâ!>W5+Ó·OU¹ìO×ŨوcDîÄ@wö­ ÿz-ŽIyý¯û=l1xãÉÒ4‚µuÕ}rUÕ–xºŸ %æßºX­W¾iCSBXùÿë!äÒ;°kæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èèÿÿ€ 66%ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿVex‡oè>¡GBRD0Uõ)úË€_á_¹nmrkà éhCü 9§"鄃Åxfºµ¬u~ˆ (k—L šSFþ« O"Ãê«6G#swtpm-0.6.3/tests/data/tpm2state4/tpm2-00.volatilestate000066400000000000000000000213241421141172300226530ustar00rootroot00000000000000 "Ô"ÄEcx‰ ¤@@eb dluohs eulav euqinu laer A .eulav euqinu a yllaer ton si sihTVex‡ ¤oè>¡GBRD0ÎWñW€;¾ÔËœ¢gàhù«H'mê<<­Éfv/«Æ2/SYˆÛ!#ìÖ˜‰vgsrê¼@   kè.¯#2@œ_H+ñ”a"žm» ßl5[I»)}‘ì-gnñé¥J† Ü]U Þ|77¶YÄ‚­©À+õjvús6;­à@å]†Y\Ñý댉¡j¼¬ó“y¦éåi!g檈¿vUŸ·ÀO4ï3HÒÕë¿iâºSe5™$¶þøÎH–Óá@\@"CS$Æ:ïŸÕ!ˆ¸&Cã‹aÚ—›/* pº…u‹:_£áWº/^ÁÈG’Gôª`N³‘ýÉ«/"Œ;/þš9tþš9tþš9té_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ 0 @é_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ 0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ @ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé_‡ 0 @%6d®¼6d®¼6d®¼A  ¤ ¤u0kkžì@¬¿')9'/rg–"î˜ÎöOUƒgòé‚ýUº1œ~¢ÍìW A²P%3á,2‰d«J(åw*¹ç4ÂÔD¹h¤…@£Zdq52eâYcPf²n¬·hÃÁ_ç gùNŠÅ`µÊ®S˜ÆÎë¼ÿ•çäϺ#ÉÀÌQ ƒªn&@êÜ9l;ihk¤ÿøE>ãNÃÀ÷ֆƤë)õ9­iw'>ì–ö¸¬±r~‘æô¡„ñÚ‚¤¥CY!ŸÐƒ^#§ÞÛO§ÜÀ ¤Ecx‰wŤa2™ÔÈÅEÕ8–+³swtpm-0.6.3/tests/data/tpm2state5/000077500000000000000000000000001421141172300167515ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpm2state5/signature.bin000066400000000000000000000004061421141172300214440ustar00rootroot00000000000000 D¡¶uËñÐCó]>³«AzòÙd¾ÙåÁ›¾/_&x¹#03–Pè†å1¬ƒùÈäA»,¹É,Øà¯‡³Zˆ°0¶Îâ¨X”“0ë kƒ¿…~7ϨUƒ–Æ%ùÜïȨ:jc™ÜÀåt‹3ä%0!£¶ìÄãa ñs‚E  <:\²7ðÜ¢~%Õ¹ &Ï.÷Hã°z¦(Oש‡ºy¿  °Ujže0m<wwÜ說^äÚy·ˆ*‚lÄÜ·¨WJŒFp¸ÿ”ÐQÀ™Êv†UmmHirršNÄkÙMP‘`¾J$ž5KP´ÂµèòRà :cíÒð¬3`swtpm-0.6.3/tests/data/tpm2state5/tpm2-00.permall000066400000000000000000002226361421141172300214410ustar00rootroot00000000000000 %ž%Ž«6G#Éêd1XÀ€€~@ ª@@ €@ @!4C@s/»§x¹ÂÒðµnU>˜ø‰/C),òº*L¥'ᥢV昨(xZ–Ñй“tÎx:Ú1V533^'@ßøs{@²æŒ ÞLvÈO2OIqF¡4¡ê> PºÜñ6@ÒK{¡À•RVAbÖN^z49é-ÐÄ^ @GìLgWüÞt~¼Ök)fAu½ Õ3õU ˜û»ñ¸ÇRû9_|5¦5Z2HÈÓFc5á)øjüc=™Ÿ¬@Pìȱy R çí°AŒZ³Je?'RgsPQû6¼Pa¡EÂ¯Ñ ßUÿ+”± ô[þø ÎJ² ¾²w@È2°óÔÿa& !O®_²f8sÿé]€h/0¡â éøäA T‰$èù3v0²–~í¼#,±Bé¸E}šÙ¡@eë\™=SØdY*dÀ{ÉNϬý8k(0sG>òº:Yû-Ï?Dmyûÿöõ@Î.õh8‡”?ûxµ-Þ…”®kæ&ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ èèÿÿ€ 66ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿVex‡oè>¡GBRD0¥#èk˶|p›Gâ¨M¤:Ï!_}ì–fK IÕ,…Q—"߯S˜®[ÎY'»ûÅ*SFþ« O"Ãêpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððpþš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp!þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp"þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp#þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp$þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp%þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp&þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp'þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp(þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp)þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp*þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp+þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp,þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp-þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp.þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp/þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp0þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp1þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp2þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp3þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp4þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp5þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp6þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp7þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp8þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp9þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp:þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp;þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp<þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp=þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp>þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ë" T{Ó÷;Lº!¦Yo]+Y´Fo>FL?n–Jððp?þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jððp@þš9tÀ8u¾s¯ r°Uy]’akvç1!3Ñ[¡ÆàN14‘þa»Ôíˆd‚«Bùi.¯8!ªÓüWñ–)–¹8lëúÅXéû„uÎÿtg'ž£ùq§Gñ|˃°P¶çžíqÀ儈òœQˆ÷K^úŒ» ë)ßÁdàµêµ;…’¨Ué•¿Ä?Ï?9Ø®›o Ñ¡=%ªG45I_?±ºe¨zŽ“‡Íþm^ë ˜°"Ì ú‡+{7yÅ׫©Ÿ¹`F³~/ç6«€ª•—ò®]ýÀzü›nõ:¾uÏ•¨Ø³.ÊŠ ‰Ghðq¿~:CѾ0ű‚¦>9z_P‘<úN±qŽ [½ŒšÊºØÔk>Œ/èhâ+J+tZ»¬Î/ß‘ €p¬þŠA¦o º[uèßîõŽv6+uÞ¢úÇÞ¯<¸nG‘¾6/ç6«€ËöyþË7ëFL?n–Jðð„%G&Z ììÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ«6G#swtpm-0.6.3/tests/data/tpmstate1/000077500000000000000000000000001421141172300166635ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpmstate1/README000066400000000000000000000005331421141172300175440ustar00rootroot00000000000000The volatile state of this TPM instance has PCR[10] = c78a6e94c73c4d7fc305c8a66bbf1545f4edb7a5 (extend of 'test') The state is not encrypted. The value of PCR 10 can be found as follows: # od -tx1 tpm-00.volatilestate [...] 0000420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c7 0000440 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 [...] swtpm-0.6.3/tests/data/tpmstate1/tpm-00.permall000066400000000000000000000022211421141172300212530ustar00rootroot00000000000000" €ýxÀv A*]Xн¼ã†ÉóWlÛ£¸ίˆswtpm-0.6.3/tests/data/tpmstate1/tpm-00.volatilestate000066400000000000000000000023171421141172300225050ustar00rootroot00000000000000 €–ô !$ÿÿÿÿ@ÇŠn”Ç ì’ëP–<r¸ Í‚Àáü¢„8ÌL¡Œæswtpm-0.6.3/tests/data/tpmstate2/000077500000000000000000000000001421141172300166645ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpmstate2/README000066400000000000000000000003211421141172300175400ustar00rootroot00000000000000The volatile state of this TPM instance has PCR[10] = c78a6e94c73c4d7fc305c8a66bbf1545f4edb7a5 (extend of 'test') The state is encrypted. The value of PCR 10 cannot easily be found in tpm-00.volatilestate. swtpm-0.6.3/tests/data/tpmstate2/pwdfile.txt000066400000000000000000000000121421141172300210500ustar00rootroot00000000000000mypasswordswtpm-0.6.3/tests/data/tpmstate2/tpm-00.permall000066400000000000000000000023001421141172300212520ustar00rootroot00000000000000pt`õ´º¦¾KÄ¡Fƒù‰ŠA‰³^;•wÚä}œÇ³?Iw¹dàÒ÷}quo'+ ‹-D ùÒ½§É&Ý¿jïKÞ?ÍV#°>zl‰Ú}-w]¶ý‡p!…¨Ì¤¯Ûò26ñº¶ÏÚ/ÞÂw>E]ûÿH«)œ·»£l¤x2ì›vÕMùLó^ë£MÐ,ÚÙÃanTe;ùS¸hÓ^z$ô0nÃl­Þù y@ø¨{ë¾LAí¢Æ—pháêïzôŒ7‡2ÏÞ?kùû&µ="‘ÛF#­Ýp=ªð¢AQ‹øÇ³0è-& ±ñ”€J¶d‹HW!„88o_k°©jר¦;q37Bl×ÚC"jªZûØR«±óPmÙÇô!Ò“UçÚv»§Ö"ÈNÔ%sÜ“¬ÓÁ£"‰¾Œ“x®˜n¸«HŸ)ø'ÔŽ^ŸZñö]¹¸E‰y!§Éùi4†røžk7N€lÒƒh+Uú)7=b¨ÃÉe:€‚/DzŹsÊ‚-¦É%5¤'v‡ªO^ÁzpÝz8Ò…’!\_’ á‡ÜøU “Öëh0þ c˪¦Y•™¶·}ìû$ ºã|y‘·{ ˃0Äd.Ó `ôÙ÷ OѶa$ZaQöö§½‡}Î÷Œ„1LÜ`êáâ¢Ø¯‹šZ §'³òvð@•;Ñ‘ûu…÷é"‰B¦wüS';—w¤äÑúwßׂ¹ê|¯»KÌUÇP áQ†ˆ5l„ŠÅ­"˜`Öm.ð3=,¨K@ÂùšQ6V‰˜ÞͶ©ø®È¤€ÓVôÝÄ’T¹ãCs ù¨£ßòåà!v±½“êa^C Z”Á Eyã>«ùÝ«vCå¨gûÒœ“ÅzPËÔui޽#+áÔÃS›xÆF@ ¢›¿iVÁ!k•DÇX­¶×u¹]OÒ6X r•¨žì‘&½õ¥k­Ö¬Ø™ ’Š,{9îJuƒyLÊúuì5p.L.4D4¦ÊÏ¥B¿Å{^#¾Üã,îZS(‹‘á{ ¦¾Hš»Œ=Ö¼cÕ ƒÏÁN›—§ya¿’´¬ÊLd¥òWË3jšw?ºï ”ÂéÌA›@Ÿõ©þ !ZáÿXÆ2]¿9U*I‚4t*1Ÿ÷0¹×ß!°²ä<¶£"gÃKJ|ûT+¬â#`¡ßk—‰("œVŒ³Ó‘”N9N9è¯;õÎ`» oË#©¡ƒÐ?0âÉâ¢Z×'È_u`ZÁklþ!Ô­¸Õ¸’½Œ='žgŽýZóì. l•Ç_Ptîk8à‡ PóAAúE„›G¢•˜W±eÍéz#y`OP,<Ñ Ïž¯ýVưÆ'Ø;; žîLAHÉC¿ö$âí}!ݬ"ùl‡ ËûnwǪêÏŸmðvjðR_oýö8Ò²W¿ÿ%MHS÷Â\HPñ5PdÝT÷W»wÇ© (ç„U/Éžeüp"{”¤$ïºøçû§äaæ±ö›H²ÚJÕ•JL¸“V¥Tü ùëLD7½Z¼þ§tÇ>qÒù‘UÒ_†å/¨ðIwÖY|,C±swtpm-0.6.3/tests/data/tpmstate2/tpm-00.volatilestate000066400000000000000000000023601421141172300225040ustar00rootroot0000000000000011ÄûÑë"JrÝn°Ž3eÄé. ]¤öÖÔÚ[Æ1”DDL•ÛÉ–5Sô“oŒ³-BŽRB")ø™Â€jºŸ$ÑÓi³B¤þí{+*Á«=—é»a:Âtš*ƒé[k³UA™T‹™*€,cc IŽ£øµºDu#/OQ-25ÕÜf"å&¼Àß)nÐШ˜Øƒo(ÒúxŠ©Ý^QB\“Æ¥÷Ô–C!Hôáël4‰–¥…xªiEÂÐq"»›©ð]ã ÇÖÑþ%âÓ$·X²$àÆÜ]Ú­aJ$€˜¢AÉÁÓÌ*ÜÓ©=е¬=;:‡½Ú±©»ò÷´õmœÇ°€P ð[C4Ú¾Úò§:L'£e«_µ ]4°ðZD‹ŽUP¶wÄ*ù·ÁFô9Xr Á@ÀoJ)¢4;næË{–ˆs?¹Î´ä1\øK‰ƒ±äËÖ<73`§L÷l귾"4‚-ŽÈïcJyÛ¡È ãJŽSsv¯m²Tʦ¶‘e± ´ siîlÝïíGÛ^õ×adA«UI2äE§üŒjÓFM®U$èÅŽ$âIL»§¡zP3˹<^š`”}à8<#’õVC2°aÐ:ìR€T—ø\C¼VrþnÏ™>lÖéœh® Öi[=µX+( xàÞç3Ùú‡;¹¦?-h jNc–u8¦`Õüéc90N¥„D7N¹ŒtÝÌm¡·iª‚hƀĥ<qF´‰/´KÀÑÀl¦ ^éêÀ=ñ”¶ªÅ·pJ,L¿|ë-)¸Ï²ÀåGdî %¢fËwò}mƒF¹¤ùrz2åÃQ.{&‡a„Ö5QGÞ¥ŽË€ ¾2Ájp²òŸ¶<+»²Jc¨¤ì÷àQñƒL# ,Þ¼}= áø ¥ËfbûÕ‘1dªòÐ!3hÔ„íp÷_^â?#ñ8e—1úq‡Åò5j2½%Qt¬÷çá #2ˆ{²Œ¿«øV¬7ÑÀ/« ÑiK™F½]n”=% ›|'ŒàGÎ"ܺ§ôIl':~¥^Qt —„[P/)\I1PÇ.¤~tZ‹:ŸúFq^‚¹R›Œ¡eaBzþ¡¿Ä@2&/%w'mx¶°àp²„?æÍA+!g¢‰ÃFÔ Þc™éÑUñ.f¿¸œuœ¾^®fEãêë1”; 347£~*±OŒ»I~ZæõÕܺ¿Hû§Ò?è7W•ÒØ¡•µµB<äÙ¢â“Aç§[ˆ&1"ÂF»Ó‘êw{.¾!Žƒg‘¤zž"+_¨òéRU ¾^î‰Ýnyc0).ۚʾ¢W\-–Ç&xs,&EýµÔ6æ?Ï7p¸¾¯?º]õô«,ìÔqªÊ©ˆyÖÆ®¦@ýdÏdéõ9Œ' ±57ÞÔ&+£‹Èßv~ƒ¼ çé–¼Bµ<á9Mùr–IY¾ZA[Vº`<½¿m&ì³›mú¿‹9à©k‰œ5x9ÐK oœÆÐ=y¤xtx¥=Æ€A£ä¨„¢Ñ( ¥§¼³ýˆ»ÙÊ¥: ä±¨z QÝL\ËM«@då¹[Ÿ©(HOáÿ›déí°úzÖYUšõä‡[ôä³Ã×ÚÓ8}³/sþ÷<'å&qd¨swtpm-0.6.3/tests/data/tpmstate2b/000077500000000000000000000000001421141172300170265ustar00rootroot00000000000000swtpm-0.6.3/tests/data/tpmstate2b/pwdfile.txt000066400000000000000000000000121421141172300212120ustar00rootroot00000000000000mypasswordswtpm-0.6.3/tests/data/tpmstate2b/tpm-00.permall000066400000000000000000000023741421141172300214270ustar00rootroot00000000000000 ü uR†‚‚ûÓ,Ä8 L>-„ÉXáå]hé\öA3dz-6:û$uߺ¼Ã“µjÔèárÁ8Ò«Ä’x¿¨Y†kŒ"·Ù‹’ÚsÁ¹?ü5"éxŸÎqÙ¿:& ÿ _ã§²tF^(õ¾’-“(!$lÙDØ=öÍÊ"«|aÑí}ʬ¥Ì&¢LJbØùJ>“óLª!ô2?Î1Ní¬óg¾B‘kBVsrüy8ŠÇvˆ±Ã<@å´JGƘ€ ’멊‹IÛªUˆw1RÖ:rp§z`žÍ[é?ÕÅvmFÍHàühž(+KMVµÓ&[Ñ­ ‰-è4IzÅ{»ÿ¥@º…*ØOñ¡ Ó'Þg]]¼#>~lÛùΕ`vm3~×Q¡ˆÕ §ÊüPPïìÒ^fÚ6Ÿºéã9 À-?ÔÎß^,“Ü-ohÙÔ'€ÌùÖäyŸö|þ¥­¤‹u: a»{¥ æ‡g^l©ê£’ÿARŠÆmúu1 Äs¢´a—õ¶ cÈXfÈU° ö•ÿ-¨³ Ÿ1*WÝBï~<’aWä”móyµÁ»¦†Iȹ…›J«öF'ŽZïêÏ& 1:¨Êd4±Zä[@ãª÷Ì•Ñ+ºÂ~÷¬54y÷±¬ÌÁƒ¥Žš0¤ÿt6{H>ŒškÀ²E(á ”Ã}ØBˆÒ‘ö@’J'ÔfgX É5‰(šõæ™ÜC„-å«PÅD´•^ÍØ³{#†éµA}ñ áœèCåg¼»#ej$}߯k|»Ü*)lJ~—M_»Ušlàg×¥;Œï§z´3B%.j'§–Db9Z ¡µLoÙ£ýWs`Od‹ /q<X؈囥ÑvÚ[Ûµ/ç^eŸ÷–"WeøHÿ_NXIC¹–˜| ¼MO½ƒ¹#î Ok¤%ÕeH¨¿ ^l<ÏÚ®ÿEIæê{¶p¥zJc;J\ðÜÒ¸­#¨;­ÛfwQ<9IO ÉŒ=ËN‰Fç¡Ø|&ûRL3 6P‹û{´¿Fƒ°€»HÜ1|@ †7Ï·Æ›7–›²ã=¯âá{–ßGy cÌ $-ÍÇ€f€DMZ`]74XýîÀ=ÞÑLõ¦‰9zîa°Ooý\nÓ ²7⚤Œ]—³~[$›tÜ™œJ%Á;’Ëjì¥!”¹YWVr4ÙªzÝÍ“HBeàsÙBfÚc©,ÓÆŸÆ.ÿ%˜v0zæ'"€¦<MlâàÁ€´ÓúÃ#M={õ!‚ª: K”…QÈÝמ÷râi‹š]x…hM~l3ö »ÍŒ±‚ A‡ºçl ¦Ð,Ï*±z¬ oîY´_´WP‘‹»Â” ÏëfåÆzGpŽî¥0ЮÿÅ/·÷)¥ x¿TÓúúM²Î ©šqÉ ›ß˜/‹Y€A<)ÉN?J¤:’˜¯ ]{8bswtpm-0.6.3/tests/data/tpmstate2b/tpm-00.volatilestate000066400000000000000000000024741421141172300226540ustar00rootroot00000000000000 <à—Î<ÿ²ã{ü™ã¡ÖB;.^j´æe–‘K%¡Ú4ÎYÔ“ç Ðí›Z~’^ﻣà` Žæâ»óÕi¶•àZ©âÇú¡ZEÓóäëÐõ»€ψ\üM‡ì‚B^$1÷áq`!«æÝ‘Ã3¨ÞßRÏŠýíRe^ä=WC¬;7“E8Óü_z:£¤§5hëÉdÓ¦ÜÒ™ãŽ<Ä7àœ€)JJ*$«áâ|ðp¦ï\õŽpQøðo’+‘˜¿Tƒƒý¼@ fë¢Z2š`Øñ”Ý.gª^ÇKͯ£âŠZ™ƒpé&íÁˆƒœ8¼¡VfÎzV }@ZŠ|N wàš G<òut‰·zdÉ"þê+šž¢¥7ÔL1Õ uZTKù"ÑK?ç3P ìèœ?&¸ü¶“ø¼A2¾I¯l4¾&ágðÓº&7?ÍMk÷«A‘²*”ºæRLÇ•FuC;œùµ&5g¤eG¾€?„æ;…¤ŸByƒÂìºYÜY¾Üwpó•éxÌspf˜¶›ßËRk“{ey;Mz+òbJ’нÃÑc§SŠ:†“½ÆƒZ“&k7:X?q·@– =R^¦/w^Ô‚ÄP©Þ—ƒ^K¯c¬v5¨2×B¹¯=’¦4­…FŸ@+·ù™!}ú<Åñ¦š)Í =`•^€‹l²å(ÀuðóšKƒÎ€7ZÖÖ{JÈ”î?Å5Ž»,hoô™ß÷‰}doWIÔ(fíO7Ú±‘!š0œ5êìÄ›©þay¤¾óÔÝ–{fˆk3zÐ2ÔQò X!µY‘ø?nû}êwÐW¹«™)J”¼Áxó#³Ï›Z¡ ¨ý½‘×älS9/|~°2vâò|¦›Ó'Y0x‰âPIºís4^P¥jï¢ê6"#渤@bóºùpr+­þ“Ý3¾'–ÿaèmÒiÆŠ²æÒ/E4Ïr•Äœv«%ÿ „ª×ìf’Þ‘F¹tÌ„„±}CA[Ö+rr‹âÞ±™8â¨ìù9_¼ü"ï˜/jê¤ÓÒìßY‘‚šE3á`ï²`|í1Î=wËpèÙSñ ®A!E4šX"‚»pÒe³?+’£ßÄä ¼–żÞI†:Åk•éŸc©¹oágÜÏ6Þ“ÂÓË1ÛFóìb'H/zp—ÎÌvÓFóˆú!}Q›Ä¼e~ö“:áÈv–²d‘¦BÈÒ  ŽnGüB@pØ(A¶œ%nC/迨©£è‡•÷TNsù×'[mœ¤ …ì©3“ÙÄÖS‹€¯´Žï¼Ôç JžÙ²0!d±›EÅ…‚Ú3î® £pPQg>)÷‹¥µýô7‡!'änNÙ…&íoÐY¯ÝïØ{D5ÓÜP %<Þ‡¦â• †4^™NÓ›ÌËrnº”׌„ª g·>teSK¨þ>ZŒ4b@Öf¿„¯ØGÞ_‰l Ö¢x—õõMgI *ÎOʯ®™«×—2OÄÖ ‘swtpm-0.6.3/tests/load_vtpm_proxy000066400000000000000000000004131421141172300171770ustar00rootroot00000000000000 # For the license, see the LICENSE file in the root directory. # Some distros may not have the device if [ ! -c /dev/vtpmx ]; then modprobe tpm_vtpm_proxy if [ $? -ne 0 ]; then echo "Skipping test using vtpm proxy module: module not available" exit 77 fi fi swtpm-0.6.3/tests/patches/000077500000000000000000000000001421141172300154575ustar00rootroot00000000000000swtpm-0.6.3/tests/patches/0001-Deactivate-test-cases-accessing-rootcerts.txt.patch000066400000000000000000000056251421141172300300050ustar00rootroot00000000000000From 850ce946fc5ba79f03d46e8cb7695dcadb5f397d Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 26 Feb 2021 18:45:57 -0500 Subject: [PATCH 1/9] Deactivate test cases accessing rootcerts.txt rootcerts.txt contains files in a drive we don't have access to --- utils/regtests/testcredential.sh | 18 +++++++++--------- utils/regtests/testunseal.sh | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/utils/regtests/testcredential.sh b/utils/regtests/testcredential.sh index cb9fec0..16fd66a 100755 --- a/utils/regtests/testcredential.sh +++ b/utils/regtests/testcredential.sh @@ -300,9 +300,9 @@ NVNAME=( ${PREFIX}createek -high -pwde eee -pwdk kkk ${CALG[i]} -cp -noflush > run.out checkSuccess $? - echo "Validate the ${CALG[i]} EK certificate against the root" - ${PREFIX}createek -high ${CALG[i]} -root certificates/rootcerts.txt > run.out - checkSuccess $? + #echo "Validate the ${CALG[i]} EK certificate against the root" + #${PREFIX}createek -high ${CALG[i]} -root certificates/rootcerts.txt > run.out + #checkSuccess $? echo "Create a signing key under the ${CALG[i]} EK using the password" ${PREFIX}create -hp 80000001 -si -pwdp kkk > run.out @@ -402,9 +402,9 @@ NVNAME=( ${PREFIX}createek -high -pwde eee -pwdk kkk ${CALG[i]} -cp -noflush > run.out checkSuccess $? - echo "Validate the ${CALG[i]} EK certificate against the root" - ${PREFIX}createek -high ${CALG[i]} -root certificates/rootcerts.txt > run.out - checkSuccess $? + #echo "Validate the ${CALG[i]} EK certificate against the root" + #${PREFIX}createek -high ${CALG[i]} -root certificates/rootcerts.txt > run.out + #checkSuccess $? echo "Create a signing key under the ${CALG[i]} EK using the password" ${PREFIX}create -hp 80000001 -si -pwdp kkk > run.out @@ -540,9 +540,9 @@ NVNAME=( ${PREFIX}createek ${ALG} -pwde eee -cp -noflush > run.out checkSuccess $? - echo "Validate the ${ALG} EK certificate against the root" - ${PREFIX}createek ${ALG} -root certificates/rootcerts.txt > run.out - checkSuccess $? + #echo "Validate the ${ALG} EK certificate against the root" + #${PREFIX}createek ${ALG} -root certificates/rootcerts.txt > run.out + #checkSuccess $? echo "Start a policy session" ${PREFIX}startauthsession -se p > run.out diff --git a/utils/regtests/testunseal.sh b/utils/regtests/testunseal.sh index aae3d4e..1755740 100755 --- a/utils/regtests/testunseal.sh +++ b/utils/regtests/testunseal.sh @@ -724,8 +724,8 @@ echo "" echo "PROVISION: Create the EK for the salted session 80000000" if [ ${CRYPTOLIBRARY} == "openssl" ]; then -${PREFIX}createek -rsa 2048 -cp -noflush -root certificates/rootcerts.txt > run.out -elif [ ${CRYPTOLIBRARY} == "mbedtls" ]; then +#${PREFIX}createek -rsa 2048 -cp -noflush -root certificates/rootcerts.txt > run.out +#elif [ ${CRYPTOLIBRARY} == "mbedtls" ]; then ${PREFIX}createek -rsa 2048 -cp -noflush > run.out fi checkSuccess $? -- 2.26.2 swtpm-0.6.3/tests/patches/0002-Implement-powerup-for-swtpm.patch000066400000000000000000000070701421141172300244500ustar00rootroot00000000000000From f0f9aec53193b1c81f2de2cc9cc52a0c82afa523 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:39:51 -0500 Subject: [PATCH 2/9] Implement powerup for swtpm --- utils/reg.sh | 12 ++++++++++++ utils/regtests/inittpm.sh | 4 ++-- utils/regtests/testevent.sh | 2 +- utils/regtests/testnvpin.sh | 4 ++-- utils/regtests/testpcr.sh | 2 +- utils/regtests/testshutdown.sh | 6 +++--- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/utils/reg.sh b/utils/reg.sh index 048863b..61f23d9 100755 --- a/utils/reg.sh +++ b/utils/reg.sh @@ -1,6 +1,12 @@ #!/bin/bash # +SWTPM_IOCTL=${SWTPM_IOCTL:-$(type -P swtpm_ioctl)} +if [ -z "${SWTPM_IOCTL}" ]; then + echo "SWTPM_IOCTL not set and could not find swtpm_ioctl in PATH" + exit 1 +fi + ################################################################################# # # # TPM2 regression test # @@ -244,6 +250,12 @@ initprimary() checkSuccess $? } +powerup() +{ + ${SWTPM_IOCTL} -i --tcp ${TPM_SERVER_NAME}:${TPM_PLATFORM_PORT} + return $? +} +export -f powerup export -f checkSuccess export -f checkWarning diff --git a/utils/regtests/inittpm.sh b/utils/regtests/inittpm.sh index eaefab4..2c87bb2 100755 --- a/utils/regtests/inittpm.sh +++ b/utils/regtests/inittpm.sh @@ -46,7 +46,7 @@ echo "Initialize TPM" echo "" echo "Power cycle" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup" @@ -62,7 +62,7 @@ ${PREFIX}pcrallocate +sha1 +sha256 +sha384 +sha512 > run.out checkSuccess $? echo "Power cycle" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup" diff --git a/utils/regtests/testevent.sh b/utils/regtests/testevent.sh index 6336920..6d78ba5 100755 --- a/utils/regtests/testevent.sh +++ b/utils/regtests/testevent.sh @@ -66,7 +66,7 @@ do do echo "Power cycle to reset IMA PCR" - ${PREFIX}powerup > run.out + powerup > run.out checkSuccess $? echo "Startup" diff --git a/utils/regtests/testnvpin.sh b/utils/regtests/testnvpin.sh index 89d14a7..c045af1 100755 --- a/utils/regtests/testnvpin.sh +++ b/utils/regtests/testnvpin.sh @@ -240,7 +240,7 @@ ${PREFIX}nvwrite -ha 01000000 -hia p -id 0 1 > run.out checkFailure $? echo "Reboot" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup" @@ -448,7 +448,7 @@ ${PREFIX}nvwrite -ha 01000000 -hia p -id 0 1 > run.out checkFailure $? echo "Reboot" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup" diff --git a/utils/regtests/testpcr.sh b/utils/regtests/testpcr.sh index ef8fa2c..e2ac737 100755 --- a/utils/regtests/testpcr.sh +++ b/utils/regtests/testpcr.sh @@ -191,7 +191,7 @@ do checkSuccess $? echo "powerup" - ${PREFIX}powerup > run.out + powerup > run.out checkSuccess $? echo "startup" diff --git a/utils/regtests/testshutdown.sh b/utils/regtests/testshutdown.sh index 566471b..7be9f1c 100755 --- a/utils/regtests/testshutdown.sh +++ b/utils/regtests/testshutdown.sh @@ -147,7 +147,7 @@ ${PREFIX}shutdown -s > run.out checkSuccess $? echo "Power cycle" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup state" @@ -255,7 +255,7 @@ ${PREFIX}shutdown -s > run.out checkSuccess $? echo "Power cycle" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup clear" @@ -331,7 +331,7 @@ ${PREFIX}shutdown -c > run.out checkSuccess $? echo "Power cycle" -${PREFIX}powerup > run.out +powerup > run.out checkSuccess $? echo "Startup clear" -- 2.26.2 swtpm-0.6.3/tests/patches/0003-Set-CRYPTOLIBRARY-to-openssl.patch000066400000000000000000000013241421141172300237570ustar00rootroot00000000000000From b233462f3fe53d2209a1e2aad7f196979cea00e5 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:35:56 -0500 Subject: [PATCH 3/9] Set CRYPTOLIBRARY to openssl --- utils/reg.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/reg.sh b/utils/reg.sh index 61f23d9..33e3299 100755 --- a/utils/reg.sh +++ b/utils/reg.sh @@ -264,7 +264,7 @@ export WARN export PREFIX export -f initprimary # hack because the mbedtls port is incomplete -export CRYPTOLIBRARY=`${PREFIX}getcryptolibrary` +export CRYPTOLIBRARY=openssl # example for running scripts with encrypted sessions, see TPM_SESSION_ENCKEY=getrandom below export TPM_SESSION_ENCKEY -- 2.26.2 swtpm-0.6.3/tests/patches/0004-Store-and-restore-volatile-state-at-every-step.patch000066400000000000000000000023771421141172300300450ustar00rootroot00000000000000From 30fd9216f9b984cd1e55da4c793e948ba5bc5a22 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:42:11 -0500 Subject: [PATCH 4/9] Store and restore volatile state at every step --- utils/reg.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/utils/reg.sh b/utils/reg.sh index 33e3299..01f6940 100755 --- a/utils/reg.sh +++ b/utils/reg.sh @@ -124,6 +124,16 @@ printUsage () echo "-51 Events" } +storeAndRestoreVolatileState() +{ + if [ ${SWTPM_TEST_STORE_VOLATILE:-0} -ne 0 ]; then + echo ">>> Storing and re-storing volatile state <<<" + ${SWTPM_IOCTL} -v --tcp ${TPM_SERVER_NAME}:${TPM_PLATFORM_PORT} + ${SWTPM_IOCTL} -i --tcp ${TPM_SERVER_NAME}:${TPM_PLATFORM_PORT} + fi +} +export -f storeAndRestoreVolatileState + checkSuccess() { if [ $1 -ne 0 ]; then @@ -133,7 +143,7 @@ if [ $1 -ne 0 ]; then else echo " INFO:" fi - +storeAndRestoreVolatileState } # FIXME should not increment past 254 @@ -146,6 +156,7 @@ if [ $1 -ne 0 ]; then else echo " INFO:" fi +storeAndRestoreVolatileState } checkFailure() @@ -157,6 +168,7 @@ if [ $1 -eq 0 ]; then else echo " INFO:" fi +storeAndRestoreVolatileState } cleanup() -- 2.29.2 swtpm-0.6.3/tests/patches/0005-Disable-tests-related-to-events.patch000066400000000000000000000011361421141172300251260ustar00rootroot00000000000000From 19ce952c3a7205585bed8cb063dc2b1f23434ba4 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:33:02 -0500 Subject: [PATCH 5/9] Disable tests related to 'events' --- utils/regtests/testevent.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/regtests/testevent.sh b/utils/regtests/testevent.sh index 6d78ba5..9252161 100755 --- a/utils/regtests/testevent.sh +++ b/utils/regtests/testevent.sh @@ -1,5 +1,6 @@ #!/bin/bash # +exit 0 ################################################################################# # # -- 2.26.2 swtpm-0.6.3/tests/patches/0006-Disable-testing-with-RSA-3072.patch000066400000000000000000000141021421141172300240640ustar00rootroot00000000000000From ca400b52d26bf4f518964faf2b2353d25a057fce Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:35:02 -0500 Subject: [PATCH 6/9] Disable testing with RSA 3072 --- utils/reg.sh | 2 +- utils/regtests/initkeys.sh | 2 +- utils/regtests/testcreateloaded.sh | 2 +- utils/regtests/testcredential.sh | 2 +- utils/regtests/testprimary.sh | 2 +- utils/regtests/testrsa.sh | 14 +++++++------- utils/regtests/testsalt.sh | 1 + utils/regtests/testsign.sh | 6 +++--- utils/regtests/testx509.sh | 2 +- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/utils/reg.sh b/utils/reg.sh index de7e181..9de1eaa 100755 --- a/utils/reg.sh +++ b/utils/reg.sh @@ -186,7 +186,7 @@ cleanup() rm -f khrpub${HALG}.bin done - for BITS in 2048 3072 + for BITS in 2048 do rm -f signrsa${BITS}priv.bin rm -f signrsa${BITS}pub.bin diff --git a/utils/regtests/initkeys.sh b/utils/regtests/initkeys.sh index 80c6adb..469b5c9 100755 --- a/utils/regtests/initkeys.sh +++ b/utils/regtests/initkeys.sh @@ -64,7 +64,7 @@ BITS=(2048 3072) for ((i = 0 ; i < 2 ; i++)) do - + [ $i -eq 1 ] && continue # skip 3072 bits echo "Create an RSA ${BITS[i]} ${SHALG[i]} storage key under the primary key" ${PREFIX}create -hp 80000000 -rsa ${BITS[i]} -halg ${SHALG[i]} -st -kt f -kt p -pol policies/policycccreate-auth.bin -opr storersa${BITS[i]}priv.bin -opu storersa${BITS[i]}pub.bin -tk storersa${BITS[i]}tk.bin -ch storersa${BITS[i]}ch.bin -pwdp sto -pwdk sto > run.out checkSuccess $? diff --git a/utils/regtests/testcreateloaded.sh b/utils/regtests/testcreateloaded.sh index d3e3eb8..76fb859 100755 --- a/utils/regtests/testcreateloaded.sh +++ b/utils/regtests/testcreateloaded.sh @@ -50,7 +50,7 @@ echo "" for HIER in "40000001" "4000000c" "4000000b" do - for ALG in "-rsa 2048" "-rsa 3072" "-ecc nistp256" "-ecc nistp384" "-ecc bnp256" "-rsa" + for ALG in "-rsa 2048" "-ecc nistp256" "-ecc nistp384" "-ecc bnp256" "-rsa" do echo "CreateLoaded primary key, parent ${HIER} ${ALG}" diff --git a/utils/regtests/testcredential.sh b/utils/regtests/testcredential.sh index 16fd66a..a68960d 100755 --- a/utils/regtests/testcredential.sh +++ b/utils/regtests/testcredential.sh @@ -287,7 +287,7 @@ NVNAME=( # interate though high range RSA EK certficates for ((i = 0 ; i < 2 ; i++)) do - + [ $i -eq 1 ] && continue # skip 3072 bits echo "Create an ${CALG[i]} EK certificate" ${PREFIX}createekcert -high ${CALG[i]} -cakey cakey.pem -capwd rrrr -pwdp ppp -pwde eee -of tmp.der > run.out checkSuccess $? diff --git a/utils/regtests/testprimary.sh b/utils/regtests/testprimary.sh index f51687f..59b1754 100755 --- a/utils/regtests/testprimary.sh +++ b/utils/regtests/testprimary.sh @@ -168,7 +168,7 @@ checkSuccess $? # different algorithms, command line options -for ALG in "-rsa 2048" "-rsa 3072" "-ecc bnp256" "-ecc nistp256" "-ecc nistp384" "-rsa" +for ALG in "-rsa 2048" "-ecc bnp256" "-ecc nistp256" "-ecc nistp384" "-rsa" do diff --git a/utils/regtests/testrsa.sh b/utils/regtests/testrsa.sh index 4f76522..e835660 100755 --- a/utils/regtests/testrsa.sh +++ b/utils/regtests/testrsa.sh @@ -55,7 +55,7 @@ echo "" echo "Generate the encryption key with openssl" if [ ${CRYPTOLIBRARY} == "openssl" ]; then - for BITS in 2048 3072 + for BITS in 2048 do echo "Generate the RSA $BITS encryption key with openssl" @@ -68,7 +68,7 @@ if [ ${CRYPTOLIBRARY} == "openssl" ]; then elif [ ${CRYPTOLIBRARY} == "mbedtls" ]; then - for BITS in 2048 3072 + for BITS in 2048 do echo "Generate the RSA $BITS encryption key with openssl" @@ -94,7 +94,7 @@ echo "" echo "RSA decryption key" echo "" -for BITS in 2048 3072 +for BITS in 2048 do echo "Load the RSA $BITS decryption key under the primary key" @@ -124,7 +124,7 @@ echo "" echo "RSA decryption key to sign with OID" echo "" -for BITS in 2048 3072 +for BITS in 2048 do echo "Load the RSA $BITS decryption key" @@ -166,7 +166,7 @@ echo "Start an HMAC auth session" ${PREFIX}startauthsession -se h > run.out checkSuccess $? -for BITS in 2048 3072 +for BITS in 2048 do for SESS in "" "-se0 02000000 1" @@ -254,7 +254,7 @@ echo "" echo "Loadexternal DER encryption key" echo "" -for BITS in 2048 3072 +for BITS in 2048 do echo "Start an HMAC auth session" @@ -410,7 +410,7 @@ rm -f deepub.bin rm -f tmpmsg.bin rm -f tmpdig.bin rm -f tmpsig.bin -for BITS in 2048 3072 +for BITS in 2048 do rm -f tmpkeypairrsa${BITS}.der rm -f tmpkeypairrsa${BITS}.pem diff --git a/utils/regtests/testsalt.sh b/utils/regtests/testsalt.sh index 1bdc1a7..57ec69e 100755 --- a/utils/regtests/testsalt.sh +++ b/utils/regtests/testsalt.sh @@ -57,6 +57,7 @@ fi for ASY in "${SALTALGS[@]}" do + [ "$ASY" = "-rsa 3072" ] && continue # skip 3072 bits for HALG in ${ITERATE_ALGS} do diff --git a/utils/regtests/testsign.sh b/utils/regtests/testsign.sh index edfa014..bb76605 100755 --- a/utils/regtests/testsign.sh +++ b/utils/regtests/testsign.sh @@ -44,7 +44,7 @@ echo "" echo "RSA Signing key" echo "" -for BITS in 2048 3072 +for BITS in 2048 do echo "Create an RSA $BITS key pair in PEM format using openssl" @@ -410,8 +410,8 @@ done rm -f tmpkeypairrsa2048.pem rm -f tmpkeypairrsa2048.der -rm -f tmpkeypairrsa3072.pem -rm -f tmpkeypairrsa3072.der +rm -f tmpkeypairrsa3072.pem &>/dev/null +rm -f tmpkeypairrsa3072.der &>/dev/null rm -f tmpkeypaireccnistp256.pem rm -f tmpkeypaireccnistp256.der rm -f tmpkeypaireccnistp384.pem diff --git a/utils/regtests/testx509.sh b/utils/regtests/testx509.sh index 813085f..f5737a8 100755 --- a/utils/regtests/testx509.sh +++ b/utils/regtests/testx509.sh @@ -59,7 +59,7 @@ SKEY=(rsa2048 rsa3072 eccnistp256 eccnistp384) for ((i = 0 ; i < 4 ; i++)) do - + [ $i -eq 1 ] && continue # skip 3072 bits echo "Load the ${SALG[i]} ${SKEY[i]} issuer key 80000001 under the primary key" ${PREFIX}load -hp 80000000 -ipr sign${SKEY[i]}rpriv.bin -ipu sign${SKEY[i]}rpub.bin -pwdp sto > run.out checkSuccess $? -- 2.26.2 swtpm-0.6.3/tests/patches/0007-Disable-rev155-test-cases.patch000066400000000000000000000011521421141172300235240ustar00rootroot00000000000000From 7a6fe0d006ef5f2c6c960aa324b3e0ca4e0afcc9 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:36:53 -0500 Subject: [PATCH 7/9] Disable rev155 test cases --- utils/regtests/testattest155.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/regtests/testattest155.sh b/utils/regtests/testattest155.sh index 0bf88aa..554a40e 100755 --- a/utils/regtests/testattest155.sh +++ b/utils/regtests/testattest155.sh @@ -1,5 +1,6 @@ #!/bin/bash # +exit 0 ################################################################################# # # -- 2.26.2 swtpm-0.6.3/tests/patches/0008-Disable-x509-test-cases.patch000066400000000000000000000011171421141172300232040ustar00rootroot00000000000000From 3dbd97928bd833f5b79e8a1f5147c7b23d4c989d Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:37:27 -0500 Subject: [PATCH 8/9] Disable x509 test cases --- utils/regtests/testx509.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/regtests/testx509.sh b/utils/regtests/testx509.sh index f5737a8..acd2c3c 100755 --- a/utils/regtests/testx509.sh +++ b/utils/regtests/testx509.sh @@ -1,5 +1,6 @@ #!/bin/bash # +exit 0 ################################################################################# # # -- 2.26.2 swtpm-0.6.3/tests/patches/0009-Disable-getcapability-TPM_CAP_ACT.patch000066400000000000000000000015221421141172300250600ustar00rootroot00000000000000From 0e64682da7e1da7b8ffdf1103b99546d31a599da Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sun, 28 Feb 2021 16:38:10 -0500 Subject: [PATCH 9/9] Disable getcapability TPM_CAP_ACT --- utils/regtests/testgetcap.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/regtests/testgetcap.sh b/utils/regtests/testgetcap.sh index 4e370cf..cd6607d 100755 --- a/utils/regtests/testgetcap.sh +++ b/utils/regtests/testgetcap.sh @@ -120,8 +120,8 @@ echo "Get Capability TPM_CAP_AUTH_POLICIES" ${PREFIX}getcapability -cap 9 -pr 40000000 > run.out checkSuccess $? -echo "Get Capability TPM_CAP_ACT" -${PREFIX}getcapability -cap a -pr 40000110 > run.out -checkSuccess $? +#echo "Get Capability TPM_CAP_ACT" +#${PREFIX}getcapability -cap a -pr 40000110 > run.out +#checkSuccess $? -- 2.26.2 swtpm-0.6.3/tests/patches/libtpm.patch000066400000000000000000000057221421141172300177750ustar00rootroot00000000000000Patch for TPM 1.2 test suite to support recent OpenSSL versions. --- lib/hmac.c.old 2017-07-28 15:44:50.000000000 -0400 +++ lib/hmac.c 2019-03-28 15:48:46.564254873 -0400 @@ -3,7 +3,7 @@ /* TPM HMAC routines */ /* Written by J. Kravitz */ /* IBM Thomas J. Watson Research Center */ -/* $Id: hmac.c 4726 2014-09-03 22:02:10Z kgoldman $ */ +/* $Id: hmac.c 4771 2017-08-31 21:12:33Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ @@ -381,16 +381,29 @@ /****************************************************************************/ uint32_t TSS_rawhmac(unsigned char *digest, const unsigned char *key, unsigned int keylen, ...) { - HMAC_CTX hmac; +#if OPENSSL_VERSION_NUMBER < 0x10100000 + HMAC_CTX hmac; +#else + HMAC_CTX *hmac; +#endif unsigned int dlen; unsigned char *data; va_list argp; -#ifdef HAVE_HMAC_CTX_CLEANUP +#if OPENSSL_VERSION_NUMBER < 0x10100000 HMAC_CTX_init(&hmac); +#else + hmac = HMAC_CTX_new(); #endif - HMAC_Init(&hmac,key,keylen,EVP_sha1()); +#if OPENSSL_VERSION_NUMBER < 0x10100000 + HMAC_Init(&hmac,key,keylen,EVP_sha1()); +#else + HMAC_Init_ex(hmac, + key, keylen, /* HMAC key */ + EVP_sha1(), /* message digest method */ + NULL); +#endif va_start(argp,keylen); for (;;) { @@ -398,14 +411,23 @@ if (dlen == 0) break; data = (unsigned char *)va_arg(argp,unsigned char *); if (data == NULL) return ERR_NULL_ARG; - HMAC_Update(&hmac,data,dlen); + +#if OPENSSL_VERSION_NUMBER < 0x10100000 + HMAC_Update(&hmac, data, dlen); +#else + HMAC_Update(hmac, data, dlen); +#endif } - HMAC_Final(&hmac,digest,&dlen); +#if OPENSSL_VERSION_NUMBER < 0x10100000 + HMAC_Final(&hmac, digest, &dlen); +#else + HMAC_Final(hmac, digest, &dlen); +#endif -#ifdef HAVE_HMAC_CTX_CLEANUP +#if OPENSSL_VERSION_NUMBER < 0x10100000 HMAC_CTX_cleanup(&hmac); #else - HMAC_cleanup(&hmac); + HMAC_CTX_free(hmac); #endif va_end(argp); return 0; --- lib/keys.c.old 2019-03-28 15:47:22.627805826 -0400 +++ lib/keys.c 2019-03-28 15:48:42.665280466 -0400 @@ -1316,8 +1316,12 @@ exp); } /* set up the RSA public key structure */ +#if OPENSSL_VERSION_NUMBER < 0x10100000 rsa->n = mod; rsa->e = exp; +#else + RSA_set0_key(rsa, mod, exp, NULL); +#endif return rsa; } --- utils/test_console.sh.old 2019-03-29 16:34:47.014890971 -0400 +++ utils/test_console.sh 2019-03-29 16:35:16.181691631 -0400 @@ -61,7 +61,7 @@ USE_HWTPM="0" export TPM_SERVER_NAME export TPM_SERVER_PORT -export TPM_TRANSPORT="0" +export TPM_TRANSPORT=${TPM_TRANSPORT:-0} export TPM_TRANSPORT_EK export TPM_TRANSPORT_EKP export TPM_TRANSPORT_SK @@ -71,7 +71,7 @@ export TPM_TRANSPORT_ENONCE export TPM_TRANSPORT_ENC export LOADKEY_VERSION="" -export TPM_AUDITING="0" +export TPM_AUDITING=${TPM_AUDITING:-0} export TPM_IS_FIPS="0" export TPM_ET_ENCRYPT_AES="0" export NO_SRK_PASSWORD=0 swtpm-0.6.3/tests/softhsm_setup000077500000000000000000000136001421141172300166610ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. # This script may not work with softhsm2 2.0.0 but with >= 2.2.0 if [ -z "$(type -P p11tool)" ]; then echo "Need p11tool from gnutls" exit 77 fi if [ -z "$(type -P softhsm2-util)" ]; then echo "Need softhsm2-util from softhsm2 package" exit 77 fi NAME=swtpm-test PIN=${PIN:-1234} SO_PIN=${SO_PIN:-1234} SOFTHSM_SETUP_CONFIGDIR=${SOFTHSM_SETUP_CONFIGDIR:-~/.config/softhsm2} export SOFTHSM2_CONF=${SOFTHSM_SETUP_CONFIGDIR}/softhsm2.conf UNAME_S="$(uname -s)" case "${UNAME_S}" in Darwin) msg=$(sudo -v -n) if [ $? -ne 0 ]; then echo "Need password-less sudo rights on OS X to change /etc/gnutls/pkcs11.conf" exit 1 fi ;; esac teardown_softhsm() { local configdir=${SOFTHSM_SETUP_CONFIGDIR} local configfile=${SOFTHSM2_CONF} local bakconfigfile=${configfile}.bak local tokendir=${configdir}/tokens softhsm2-util --token "${NAME}" --delete-token &>/dev/null case "${UNAME_S}" in Darwin*) if [ -f /etc/gnutls/pkcs11.conf.bak ]; then sudo rm -f /etc/gnutls/pkcs11.conf sudo mv /etc/gnutls/pkcs11.conf.bak \ /etc/gnutls/pkcs11.conf &>/dev/null fi ;; esac if [ -f "$bakconfigfile" ]; then mv "$bakconfigfile" "$configfile" else rm -f "$configfile" fi if [ -d "$tokendir" ]; then rm -rf "${tokendir}" fi return 0 } setup_softhsm() { local msg tokenuri keyuri local configdir=${SOFTHSM_SETUP_CONFIGDIR} local configfile=${SOFTHSM2_CONF} local bakconfigfile=${configfile}.bak local tokendir=${configdir}/tokens local rc case "${UNAME_S}" in Darwin*) if [ -f /etc/gnutls/pkcs11.conf.bak ]; then echo "/etc/gnutls/pkcs11.conf.bak already exists; need to 'teardown' first" return 1 fi sudo mv /etc/gnutls/pkcs11.conf \ /etc/gnutls/pkcs11.conf.bak &>/dev/null if [ $(id -u) -eq 0 ]; then SONAME="$(sudo -u nobody brew ls --verbose softhsm | \ grep -E "\.so$")" else SONAME="$(brew ls --verbose softhsm | \ grep -E "\.so$")" fi sudo mkdir -p /etc/gnutls &>/dev/null sudo bash -c "echo "load=${SONAME}" > /etc/gnutls/pkcs11.conf" ;; esac if ! [ -d $configdir ]; then mkdir -p $configdir fi mkdir -p ${tokendir} if [ -f $configfile ]; then mv "$configfile" "$bakconfigfile" fi if ! [ -f $configfile ]; then cat <<_EOF_ > $configfile directories.tokendir = ${tokendir} objectstore.backend = file log.level = DEBUG slots.removable = false _EOF_ fi msg=$(p11tool --list-tokens 2>&1 | grep "token=${NAME}" | tail -n1) if [ $? -ne 0 ]; then echo "Could not list existing tokens" echo "$msg" fi tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p') if [ -z "$tokenuri" ]; then msg=$(softhsm2-util \ --init-token --pin ${PIN} --so-pin ${SO_PIN} \ --free --label ${NAME} 2>&1) if [ $? -ne 0 ]; then echo "Could not initialize token" echo "$msg" return 2 fi slot=$(echo "$msg" | \ sed -n 's/.* reassigned to slot \([0-9]*\)$/\1/p') if [ -z "$slot" ]; then slot=$(softhsm2-util --show-slots | \ grep -E "^Slot " | head -n1 | sed -n 's/Slot \([0-9]*\)/\1/p') if [ -z "$slot" ]; then echo "Could not parse slot number from output." echo "$msg" return 3 fi fi msg=$(p11tool --list-tokens 2>&1 | \ grep "token=${NAME}" | tail -n1) if [ $? -ne 0 ]; then echo "Could not list existing tokens" echo "$msg" fi tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p') if [ -z "${tokenuri}" ]; then echo "Could not get tokenuri!" return 4 fi # more recent versions of p11tool have --generate-privkey ... msg=$(GNUTLS_PIN=$PIN p11tool \ --generate-privkey=rsa --label mykey --login \ "${tokenuri}" 2>&1) if [ $? -ne 0 ]; then # ... older versions have --generate-rsa msg=$(GNUTLS_PIN=$PIN p11tool \ --generate-rsa --label mykey --login \ "${tokenuri}" 2>&1) if [ $? -ne 0 ]; then echo "Could not create RSA key!" echo "$msg" return 5 fi fi fi getkeyuri_softhsm $slot rc=$? if [ $rc -ne 0 ]; then teardown_softhsm fi return $rc } _getkeyuri_softhsm() { local msg tokenuri keyuri msg=$(p11tool --list-tokens 2>&1 | grep "token=${NAME}") if [ $? -ne 0 ]; then echo "Could not list existing tokens" echo "$msg" return 5 fi tokenuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p') if [ -z "$tokenuri" ]; then echo "Could not get token URL" echo "$msg" return 6 fi msg=$(p11tool --list-all ${tokenuri} 2>&1) if [ $? -ne 0 ]; then echo "Could not list object under token $tokenuri" echo "$msg" softhsm2-util --show-slots return 7 fi keyuri=$(echo "$msg" | sed -n 's/.*URL: \([[:print:]*]\)/\1/p') if [ -z "$keyuri" ]; then echo "Could not get key URL" echo "$msg" return 8 fi echo "$keyuri" return 0 } getkeyuri_softhsm() { local keyuri rc keyuri=$(_getkeyuri_softhsm) rc=$? if [ $rc -ne 0 ]; then return $rc fi echo "keyuri: $keyuri?pin-value=${PIN}&module-name=softhsm2" return 0 } getpubkey_softhsm() { local keyuri rc keyuri=$(_getkeyuri_softhsm) rc=$? if [ $rc -ne 0 ]; then return $rc fi GNUTLS_PIN=${PIN} p11tool --export-pubkey "${keyuri}" --login 2>/dev/null return $? } usage() { cat <<_EOF_ Usage: $0 [command] Supported commands are: setup : Setup the user's account for softhsm and create a token and key with a test configuration getkeyuri : Get the key's URL; may only be called after setup getpubkey : Get the public key in PEM format; may only be called after setup teardown : Remove the temporary softhsm test configuration _EOF_ } main() { local ret if [ $# -lt 1 ]; then usage $0 echo -e "Missing command.\n\n" return 1 fi case "$1" in setup) setup_softhsm ret=$? ;; getkeyuri) getkeyuri_softhsm ret=$? ;; getpubkey) getpubkey_softhsm ret=$? ;; teardown) teardown_softhsm ret=$? ;; *) echo -e "Unsupported command: $1\n\n" usage $0 ret=1 esac return $ret } main "$@" exit $? swtpm-0.6.3/tests/swtpm_setup.conf000066400000000000000000000001161421141172300172670ustar00rootroot00000000000000# Program invoked for creating certificates create_certs_tool=create_certs.sh swtpm-0.6.3/tests/test_clientfds.py000077500000000000000000000054161421141172300174250ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys import socket import subprocess import time import struct child = None fd = -1 ctrlfd = -1 def wait_for_pidfile(pidfile, timeout): while timeout != 0: if os.path.exists(pidfile): return True time.sleep(1) timeout -= 1 return False def spawn_swtpm(): global child, fd, ctrlfd _fd, fd = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM) _ctrlfd, ctrlfd = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM) swtpm_exe = os.getenv('SWTPM_EXE') tpmpath = os.getenv('TPMDIR') pidfile = os.getenv('PID_FILE') if not swtpm_exe or not tpmpath or not pidfile: print("Missing test environment \n swtpm_exe=%s,\n" " tpmpath=%s\n pidfile=%s" % (swtpm_exe, tpmpath, pidfile)) return False cmd = swtpm_exe + " socket --fd=" + str(_fd.fileno()) cmd += " --ctrl type=unixio,clientfd=" + str(_ctrlfd.fileno()) cmd += " --pid file=" + pidfile + " --tpmstate dir=" + tpmpath if os.getenv('SWTPM_TEST_SECCOMP_OPT'): cmd += " " + os.getenv('SWTPM_TEST_SECCOMP_OPT') print("Running child cmd: %s" % cmd) try: if sys.version_info[0] >= 3: child = subprocess.Popen(cmd.split(), pass_fds=[_fd.fileno(), _ctrlfd.fileno()]) else: child = subprocess.Popen(cmd.split()) except OSError as err: print("OS error: %d" % err.errno) return False print("Child PID: %d" % child.pid) if not wait_for_pidfile(pidfile, 3): print("waitpid timeout") child.kill() child = None return False return True def test_get_caps(): global ctrlfd # test get capabilities # CMD_GET_CAPABILITY = 0x00 00 00 01 cmd_get_caps = bytearray([0x00, 0x00, 0x00, 0x01]) expected_caps = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff]) def toString(arr): return ' '.join('{:02x}'.format(x) for x in arr) try: ctrlfd.sendall(cmd_get_caps) except SocketError as e: print("SocketError") buf = ctrlfd.recv(8) if buf: caps = bytearray(buf) if caps == expected_caps: return True else: print("Unexpected reply for CMD_GET_CAPABILITY: \n" " actual: %s\n expected: %s" % (toString(caps), toString(expected_caps))) return False else: print("Null reply from swtpm") return False if __name__ == "__main__": try: if not spawn_swtpm() or not test_get_caps(): res = 1 else: res = 0 except: print("__Exception: ", sys.exc_info()) res = -1 if child: child.terminate() sys.exit(res) swtpm-0.6.3/tests/test_commandline000077500000000000000000000066521421141172300173140ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. if [ "$(uname -s)" != "Linux" ]; then # Due to netstat echo "This test only runs only Linux." exit 77 fi ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} # need SWTPM to be set source ${TESTDIR}/common TPMDIR=`mktemp -d` PID_FILE=$TPMDIR/${SWTPM}.pid LOG_FILE=$TPMDIR/${SWTPM}.log source ${TESTDIR}/test_common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } PORT=11234 export TCSD_TCP_DEVICE_HOSTNAME=localhost export TCSD_TCP_DEVICE_PORT=$PORT export TCSD_USE_TCP_DEVICE=1 # Test 1: test port and directory command line parameters; use log level 20 FILEMODE=641 exec 100<>$LOG_FILE $SWTPM_EXE socket \ -p $PORT \ --tpmstate dir=$TPMDIR,mode=$FILEMODE \ --pid file=$PID_FILE \ --log fd=100,level=20 \ --flags not-need-init \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! exec 100>&- if wait_port_open $PORT $PID 4; then echo "Test 1 failed: TPM did not open port $PORT" exit 1 fi kill_quiet -0 $PID if [ $? -ne 0 ]; then echo "Test 1 failed: TPM process not running" exit 1 fi if wait_for_file $PID_FILE 3; then echo "Error: ${SWTPM_INTERFACE} TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE ${SWTPM_BIOS} &>/dev/null if [ $? -ne 0 ]; then echo "Test 1 failed: tpm_bios did not work" exit 1 fi filemode=$(get_filemode ${TPMDIR}/tpm-00.permall) if [ "$filemode" != "$FILEMODE" ]; then echo "Filemode bits are wrong" echo "Expected: $FILEMODE" echo "Actual : $filemode" exit 1 fi check_logfile_patterns_level_20 $LOG_FILE rm -f $LOG_FILE kill_quiet -SIGTERM $PID &>/dev/null wait_process_gone $PID 2 exec 20<&1-; exec 21<&2- kill_quiet -0 $PID &>/dev/null RES=$? exec 1<&20-; exec 2<&21- if [ $RES -eq 0 ]; then kill_quiet -SIGKILL $PID echo "Test 1 failed: TPM process did not terminate on SIGTERM" exit 1 fi echo "Test 1 passed" cleanup # Test 2: test port, directory and terminate command line parameters (-t) # that causes the swtpm process to exit upon connection close TPMDIR=`mktemp -d` $SWTPM_EXE socket \ --flags not-need-init \ -p $PORT \ --tpmstate dir=$TPMDIR \ -t \ ${SWTPM_TEST_SECCOMP_OPT} &>/dev/null & PID=$! if wait_port_open $PORT $PID 4; then echo "Test 1 failed: TPM did not open port $PORT" exit fi exec 20<&1-; exec 21<&2- kill_quiet -0 $PID RES=$? exec 1<&20-; exec 2<&21- if [ $RES -ne 0 ]; then echo "Test 2 failed: TPM process not running" exit 1 fi exec 100<>/dev/tcp/localhost/$PORT if [ $? -ne 0 ]; then echo "Test 2 failed: Could not connect to TPM" exit 1 fi exec 100>&- if wait_port_closed $PORT $PID 8; then echo "Test 2 failed: TPM did not close port" exit 1 fi if wait_process_gone $PID 4; then echo "Test 2 failed: TPM process did not shut down" exit 1 fi exec 20<&1-; exec 21<&2- kill_quiet -0 $PID RES=$? exec 1<&20-; exec 2<&21- if [ $RES -eq 0 ]; then kill_quiet -SIGKILL $PID echo "Test 2 failed: TPM process did not terminate on connection loss" exit 1 fi echo "Test 2 passed" # Test 3: test --fd= and --ctrl type=unxio,clientfd= # The python script execs swtpm with client sockets exec 20<&1-; exec 21<&2- LOG=$(PID_FILE=$TPMDIR/swtpm.pid SWTPM_EXE=$SWTPM_EXE TPMDIR=$TPMDIR exec $TESTDIR/test_clientfds.py) RES=$? exec 1<&20-; exec 2<&21- if [ $RES -ne 0 ]; then echo "Test 3 failed: $LOG" exit 1 fi echo "Test 3 passed" exit 0 swtpm-0.6.3/tests/test_common000066400000000000000000000022201421141172300162760ustar00rootroot00000000000000 # For the license, see the LICENSE file in the root directory. function wait_for_file() { local filename="$1" local timeout="$2" local loops=$((timeout * 10)) loop for ((loop=0; loop/dev/null fi } SWTPM_INTERFACE=socket+unix SWTPM_SERVER_PORT=65430 SWTPM_SERVER_NAME=localhost source ${TESTDIR}/common # Test 1: test the control channel on the socket tpm # OS X would not allow nobody to access the $TPMDIR easily; skip it if [ $(id -u) -eq 0 ] && [ "$(uname -s)" != "Darwin" ]; then FOWNER=",uid=nobody,gid=$(id -Gn nobody | cut -d" " -f1)" FILEOWNER="$(id -u nobody) $(id -G nobody | cut -d" " -f1)" RUNAS="--runas nobody" chown nobody $TPMDIR if [ $? -ne 0 ]; then echo "Error: Could not change ownership of $TPMDIR" exit 1 fi fi if [[ "$(uname -s)" =~ CYGWIN_NT- ]]; then FILEMODE=661 else FILEMODE=621 fi case "$(uname -s)" in FreeBSD) kldload pty ;; esac # use a pseudo terminal if [ -c /dev/ptmx ]; then exec 100<>/dev/ptmx elif [ -c /dev/ptm ]; then exec 100<>/dev/ptm else echo "Could not find chardev for opening file descriptor." exit 1 fi case $(uname -s) in Linux|CYGWIN_NT-|Darwin) PIDPARAM="fd=101" exec 101<>$PID_FILE ;; *) PIDPARAM="file=$PID_FILE" ;; esac $SWTPM_EXE socket \ --fd 100 \ --tpmstate dir=$TPMDIR \ --pid $PIDPARAM \ --ctrl type=unixio,path=$SWTPM_CTRL_UNIX_PATH,mode=${FILEMODE}${FOWNER} \ --log file=$LOG_FILE,level=20 \ $RUNAS \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! exec 100>&- exec 101>&- if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')" if [[ "$(uname -s)" =~ (Linux|OpenBSD|FreeBSD|NetBSD|Darwin|DragonFly) ]]; then exp=" 00 00 00 00 00 00 7f ff" else exp=" 00 00 00 00 00 00 6f ff" fi if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_GET_CAPABILITY:" echo " actual : $res" echo " expected: $exp" exit 1 fi filemode=$(get_filemode $SWTPM_CTRL_UNIX_PATH) if [ "$filemode" != "$FILEMODE" ]; then echo "Filemode bits are wrong" echo "Expected: $FILEMODE" echo "Actual : $filemode" exit 1 fi fileowner=$(get_fileowner $SWTPM_CTRL_UNIX_PATH) if [ -n "$FILEOWNER" ] && [ "$fileowner" != "$FILEOWNER" ]; then echo "File ownership is wrong" echo "Expected: $FILEOWNER" echo "Actual : $fileowner" exit 1 fi # Send TPM_Init to the TPM: CMD_INIT = 0x00 00 00 02 + flags res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x02\x00\x00\x00\x00')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_INIT:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send unknown command to the TPM res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\xff\xff')" exp=" 00 00 00 0a" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from sending unsupported command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0a')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_STORE_VOLATILE:" echo " actual : $res" echo " expected: $exp" exit 1 fi if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0e')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_STOP:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0f')" exp=" 00 00 00 00 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_CONFIG:" echo " actual : $res" echo " expected: $exp" exit 1 fi # To enable coverage of the above running as non-root we change the .gcda # files' ownership with this small hack if [ $(id -u) -eq 0 ] && [ "$(uname -s)" != "Darwin" ]; then find $ROOT -name *.gcda -exec chown nobody {} \; fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi check_logfile_patterns_level_20 $LOG_FILE rm -f $LOG_FILE echo "OK" # Test 2: test the control channel on the socket tpm # There are a few more tests here that require sending commands to the TPM # use a pseudo terminal run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --log file=$LOG_FILE \ --flags startup-clear \ $RUNAS PID=$SWTPM_PID if wait_for_file ${PID_FILE} 4; then echo "Error: Socket TPM did not write pidfile." cat $LOG_FILE exit 1 fi validate_pidfile $PID $PID_FILE swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')" if [[ "$(uname -s)" =~ (Linux|OpenBSD|FreeBSD|NetBSD|Darwin|DragonFly) ]]; then exp=" 00 00 00 00 00 00 7f ff" else exp=" 00 00 00 00 00 00 6f ff" fi if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_CAPABILITY:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send unknown command to the TPM res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\xff\xff')" exp=" 00 00 00 0a" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending unsupported command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Startup the TPM; we use --flags startup-clear, so expect this to fail with error 0x26 (INVALID POST INIT) res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01')" exp=' 00 c4 00 00 00 0a 00 00 00 26' if [ "$res" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $res" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0a')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_STORE_VOLATILE:" echo " actual : $res" echo " expected: $exp" exit 1 fi if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # 1. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x04')" exp=" 00 00 00 00 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_GET_TPMESTABLISHED command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 2. Send command to start HASH : CMD_HASH_START = 00 00 00 06 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x06')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_HASH_START command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 2.1. Send command to hash data : CMD_HASH_DATA = 00 00 00 07 uint32(length) data # We send 0x100 null bytes echo -en '\x00\x00\x00\x07\x00\x00\x20\x00' > $CMD_PATH dd if=/dev/zero count=$((0x2000)) bs=1 >> $CMD_PATH 2>/dev/null socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SWTPM_CTRL_UNIX_PATH 2>&1 | \ sed -n '/^ /p' | \ tail -n1 > $RESP_PATH res="$(cat $RESP_PATH)" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_HASH_DATA command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 3. Send command to end HASH : CMD_HASH_END = 00 00 00 08 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x08')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_HASH_END command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 4. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x04')" exp=" 00 00 00 00 01 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_GET_TPMESTABLISHED command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 5. Send command to reset TPM established flag: CMD_RESET_TPMESTABLISHED = 00 00 00 0b 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0b\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_GET_TPMESTABLISHED command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # 6. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x04')" exp=" 00 00 00 00 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from sending CMD_GET_TPMESTABLISHED command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Read PCR 17 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11')" exp=' 00 c4 00 00 00 1e 00 00 00 00 c4 e1 e1 c9 81 c0 cd b1 e0 43 df 97 20 72 f9 5d a9 ff 06 ff' if [ "$res" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $res" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c # cmd | flags | type | offset | res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00')" # result | flags | totlength | length | exp=" 00 00 00 00 00 00 00 00 00 00 04 e5 00 00 04 e5" if [ "${res:0:48}" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_STATEBLOB:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0e')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_STOP:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Read PCR 17 -- should fail now swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11')" exp=' 00 c4 00 00 00 0a 00 00 00 09' if [ "$res" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $res" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0f')" exp=" 00 00 00 00 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_CONFIG:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi # Expecting to see an error message for the unknown command check_logfile_patterns_level_1 $LOG_FILE 1 rm -f $LOG_FILE echo "OK" # Test 3: test the control channel on the socket tpm: resume encrypted state # copy all the state files cp ${TESTDIR}/data/tpmstate2/* ${TPMDIR} run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --key pwdfile=${TESTDIR}/data/tpmstate2/pwdfile.txt,kdf=sha512 \ --log file=$LOG_FILE,level=20 \ --flags not-need-init PID=$SWTPM_PID if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a')" exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$res" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $res" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c # cmd | flags | type | offset | vstate="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00')" # result | flags | totlength | length | exp=" 00 00 00 00 00 00 00 02 00 00 05 22 00 00 05 22" if [ "${vstate:0:48}" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_STATEBLOB:" echo " actual : ${vstate:0:48}" echo " expected: $exp" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi check_logfile_patterns_level_20 $LOG_FILE rm -f $LOG_FILE echo "OK" # remove volatile state rm -f $TPMDIR/*.volatilestate run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --key pwdfile=${TESTDIR}/data/tpmstate2/pwdfile.txt,kdf=sha512 \ --log file=$LOG_FILE \ --flags not-need-init PID=$SWTPM_PID if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 -- this should fail now swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a')" exp=' 00 c4 00 00 00 0a 00 00 00 26' if [ "$res" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $res" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0e')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_STOP:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send the volatile state to the TPM (while it is stopped) # | cmd | flags | type | vstate=${vstate:48} size=$((${#vstate} / 3)) size=$(printf "%08x" $size | sed 's/\([0-9a-f]\{2\}\)/\\x\1/g') vstate=$(echo "${vstate}" | sed 's/ /\\x/g') res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} "\x00\x00\x00\x0d\x00\x00\x00\x02\x00\x00\x00\x02${size}${vstate}")" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_SET_STATEBLOB:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send init command to the TPM: CMD_INIT = 00 00 00 02 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x02\x00\x00\x00\x00')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_INIT:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Read PCR 10 -- has to return same result as before swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a')" exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$res" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $res" exit 1 fi # Reset PCR 20 while in locality 0 -- should not work swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10')" exp=' 00 c4 00 00 00 0a 00 00 00 33' if [ "$res" != "$exp" ]; then echo "Error: Trying to reset PCR 20 in locality 0 returned unexpected result" echo "expected: $exp" echo "received: $res" exit 1 fi # In locality 2 we can reset PCR 20 # Set the localoty on the TPM: CMD_SET_LOCALITY = 00 00 00 05 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x05\x02')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_SET_LOCALITY:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Reset PCR 20 while in locality 2 -- has to work swtpm_open_cmddev ${SWTPM_INTERFACE} 100 res="$(swtpm_cmd_tx ${SWTPM_INTERFACE} '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10')" exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$res" != "$exp" ]; then echo "Error: Could not reset PCR 20 in locality 2" echo "expected: $exp" echo "received: $res" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi # (Currently) expecting to see nothing in the log file check_logfile_patterns_level_1 $LOG_FILE 0 rm -f $LOG_FILE echo "OK" exit 0 swtpm-0.6.3/tests/test_ctrlchannel2000077500000000000000000000315651421141172300174060ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} SWTPM_IOCTL=${SWTPM_IOCTL:-$ROOT/src/swtpm_ioctl/swtpm_ioctl} TPMDIR=`mktemp -d` PID_FILE=$TPMDIR/${SWTPM}.pid SOCK_PATH=$TPMDIR/sock CMD_PATH=$TPMDIR/cmd RESP_PATH=$TPMDIR/resp VOLATILESTATE=$TPMDIR/volatile source ${TESTDIR}/common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } # Test 1: test the control channel on the chardev tpm # use a pseudo terminal exec 100<>/dev/ptmx $SWTPM_EXE chardev \ --fd 100 \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Chardev TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 act=$($SWTPM_IOCTL --unix $SOCK_PATH -c 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CAPABILITY failed: $act" exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send TPM_Init to the TPM: CMD_INIT = 0x00 00 00 02 + flags act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f act=$($SWTPM_IOCTL --unix $SOCK_PATH -g 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CONFIG failed: $act" exit 1 fi exp="ptm configuration flags: 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi echo "OK" # Test 2: test the control channel on the socket tpm # There are a few more tests here that require sending commands to the TPM BINDADDR="127.0.0.1" case $(uname -s) in Linux*) # make sure IPv6 is available ip -6 addr show lo | grep -q " ::1/128" && BINDADDR="::1" ;; esac # use a pseudo terminal $SWTPM_EXE socket \ --server port=65431,disconnect=true,bindaddr=$BINDADDR \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 act=$($SWTPM_IOCTL --unix $SOCK_PATH -c 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CAPABILITY failed: $act" exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send TPM_Init to the TPM: CMD_INIT = 0x00 00 00 02 + flags act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # Startup the TPM msg=$($SWTPM_BIOS --tcp ${BINDADDR}:65431 -o 2>&1) if [ $? -ne 0 ]; then echo "Error: Failed to startup TPM: $msg" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # 1. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 0" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # 2. Hash the given data data="a" while [ ${#data} -lt $((0x2000)) ]; do data="${data}${data}" done act=$($SWTPM_IOCTL --unix $SOCK_PATH -h $data 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL data hashing failed: $act" exit 1 fi # 3. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 1" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # 4. Send command to reset TPM established flag: CMD_RESET_TPMESTABLISHED = 00 00 00 0b 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -r 3 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_RESET_TPMESTABLISHED failed: $act" exit 1 fi # 5. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 0" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # Read PCR 17 exec 100<>/dev/tcp/${BINDADDR}/65431 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100 RES=$(cat <&100 | od -t x1 -A n | tr -d "\n") exp=' 00 c4 00 00 00 1e 00 00 00 00 f9 87 3e 96 6b 9e 46 c8 45 46 2d 1f f2 52 eb cc c1 9b df fd' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c act=$($SWTPM_IOCTL --unix $SOCK_PATH --save volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_STATEBLOB failed: $act" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Read PCR 17 -- should fail now exec 100<>/dev/tcp/${BINDADDR}/65431 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100 RES=$(cat <&100 | od -t x1 -A n | tr -d "\n") exp=' 00 c4 00 00 00 0a 00 00 00 09' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f act=$($SWTPM_IOCTL --unix $SOCK_PATH -g 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CONFIG failed: $act" exit 1 fi exp="ptm configuration flags: 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi echo "OK" # Test 3: test the control channel on the socket tpm: resume encrypted state # copy all the state files cp ${TESTDIR}/data/tpmstate2/* ${TPMDIR} $SWTPM_EXE socket \ --server port=65431,disconnect=true \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --key pwdfile=${TESTDIR}/data/tpmstate2/pwdfile.txt,kdf=sha512 \ --flags not-need-init \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 exec 100<>/dev/tcp/localhost/65431 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c rm -f $VOLATILESTATE act=$($SWTPM_IOCTL --unix $SOCK_PATH --save volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_STATEBLOB failed: $act" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi # remove volatile state rm -f $TPMDIR/*.volatilestate $SWTPM_EXE socket \ --server port=65431,disconnect=true \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --key pwdfile=${TESTDIR}/data/tpmstate2/pwdfile.txt,kdf=sha512 \ --flags not-need-init \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 -- this should fail now exec 100<>/dev/tcp/localhost/65431 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 00 c4 00 00 00 0a 00 00 00 26' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Send the volatile state to the TPM (while it is stopped) $SWTPM_IOCTL --unix $SOCK_PATH --load volatile $VOLATILESTATE #act=$($SWTPM_IOCTL --unix $SOCK_PATH --load volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SET_STATEBLOB failed: $act" exit 1 fi # Send init command to the TPM: CMD_INIT = 00 00 00 02 act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # Read PCR 10 -- has to return same result as before exec 100<>/dev/tcp/localhost/65431 echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x0a' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 00 c4 00 00 00 1e 00 00 00 00 c7 8a 6e 94 c7 3c 4d 7f c3 05 c8 a6 6b bf 15 45 f4 ed b7 a5' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset PCR 20 while in locality 0 -- should not work exec 100<>/dev/tcp/localhost/65431 echo -en '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10' >&100 RES=$(cat <&100 | od -t x1 -A n) exp=' 00 c4 00 00 00 0a 00 00 00 33' if [ "$RES" != "$exp" ]; then echo "Error: Trying to reset PCR 20 in locality 0 returned unexpected result" echo "expected: $exp" echo "received: $RES" exit 1 fi # In locality 2 we can reset PCR 20 # Set the locality on the TPM: CMD_SET_LOCALITY = 00 00 00 05 act=$($SWTPM_IOCTL --unix $SOCK_PATH -l 2 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SET_LOCALITY failed: $act" exit 1 fi # Reset PCR 20 while in locality 2 -- has to work exec 100<>/dev/tcp/localhost/65431 echo -en '\x00\xC1\x00\x00\x00\x0F\x00\x00\x00\xC8\x00\x03\x00\x00\x10' >&100 RES=$(cat <&100 | od -t x1 -A n) exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could not reset PCR 20 in locality 2" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: Socket TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_ctrlchannel3000077500000000000000000000021661421141172300174020ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} TPMDIR=`mktemp -d` SWTPM_CTRL_UNIX_PATH=$TPMDIR/sock PID_FILE=$TPMDIR/swtpm.pid LOG_FILE=$TPMDIR/swtpm.log source ${TESTDIR}/test_common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } source ${TESTDIR}/common if ! [[ "$(uname -s)" =~ Linux ]]; then echo "Need Linux to run UnixIO test for CMD_SET_DATAFD." exit 77 fi # Test CMD_SET_DATAFD cp ${TESTDIR}/data/tpmstate1/* ${TPMDIR} $SWTPM_EXE socket \ --flags not-need-init \ --ctrl type=unixio,path=$SWTPM_CTRL_UNIX_PATH \ --tpmstate dir=$TPMDIR \ -t \ --pid file=$PID_FILE \ --log file=$LOG_FILE,level=20 \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi LOG=$(SOCK_PATH=$SWTPM_CTRL_UNIX_PATH exec $TESTDIR/test_setdatafd.py) res=$? if [ $res -ne 0 ]; then echo "Error: CMD_SET_DATAFD failed: $LOG" exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_ctrlchannel4000077500000000000000000000065601421141172300174050ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} TPMDIR=`mktemp -d` SWTPM_CTRL_UNIX_PATH=$TPMDIR/sock PID_FILE=$TPMDIR/swtpm.pid LOG_FILE=$TPMDIR/swtpm.log source ${TESTDIR}/test_common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } SWTPM_INTERFACE=socket+unix source ${TESTDIR}/common # Test 1: test the control channel on the chardev tpm exec 100<>/dev/ptmx $SWTPM_EXE chardev \ --fd 100 \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SWTPM_CTRL_UNIX_PATH \ --log file=$LOG_FILE,level=20 \ ${SWTPM_TEST_SECCOMP_OPT} & exec 100>&- if wait_for_file $PID_FILE 3; then echo "Error: Chardev TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')" exp=" 00 00 00 00 00 00 7f ff" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_GET_CAPABILITY:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send TPM_Init to the TPM: CMD_INIT = 0x00 00 00 02 + flags res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x02\x00\x00\x00\x00')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_INIT:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send unknown command to the TPM res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\xff\xff')" exp=" 00 00 00 0a" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from sending unsupported command:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0a')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_STORE_VOLATILE:" echo " actual : $res" echo " expected: $exp" exit 1 fi if [ ! -r $TPMDIR/tpm-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0e')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_STOP:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x0f')" exp=" 00 00 00 00 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Socket TPM: Unexpected response from CMD_GET_CONFIG:" echo " actual : $res" echo " expected: $exp" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x03')" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi check_logfile_patterns_level_20 $LOG_FILE rm -f $LOG_FILE echo "OK" swtpm-0.6.3/tests/test_cuse000066400000000000000000000011521421141172300157500ustar00rootroot00000000000000 # For the license, see the LICENSE file in the root directory. if ! [[ "$(uname -s)" =~ Linux ]]; then echo "Need Linux to run test with CUSE interface." exit 77 fi if [ "$(id -u)" -ne 0 ]; then echo "Need to be root to run test with CUSE interface." exit 77 fi if [ -z "$(grep -E '#[[:blank:]]*define[[:blank:]]+WITH_CUSE[[:blank:]]+1[[:blank:]]*$' \ ${PWD}/../config.h)" ]; then echo "Skipping test: swtpm was not compiled with CUSE interface" exit 77 fi if [ ! -c /dev/cuse ]; then modprobe cuse if [ $? -ne 0 ]; then echo "Skipping test using CUSE module: module not availabe" exit 77 fi fi swtpm-0.6.3/tests/test_encrypted_state000077500000000000000000000015301421141172300202110ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65400 export SWTPM_CTRL_PORT=65401 bash _test_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65400 bash _test_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_getcap000077500000000000000000000014531421141172300162630ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65402 export SWTPM_CTRL_PORT=65403 bash _test_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65402 bash _test_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_hashing000077500000000000000000000014601421141172300164370ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65404 export SWTPM_CTRL_PORT=65405 bash _test_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65404 bash _test_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_hashing2000077500000000000000000000014651421141172300165260ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65406 export SWTPM_CTRL_PORT=65407 bash _test_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65406 bash _test_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_init000077500000000000000000000014411421141172300157600ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65408 export SWTPM_CTRL_PORT=65409 bash _test_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65408 bash _test_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_locality000077500000000000000000000014651421141172300166430ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65410 export SWTPM_CTRL_PORT=65411 bash _test_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65410 bash _test_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_migration_key000077500000000000000000000015161421141172300176610ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65412 export SWTPM_CTRL_PORT=65413 bash _test_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65412 bash _test_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_parameters000077500000000000000000000100401421141172300171530ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..} PATH=$ROOT/src/swtpm:$PATH PARAMETERS=( "" "--createek" "--take-ownership" "--createek --lock-nvram" "--take-ownership --lock-nvram" "--lock-nvram" "--take-ownership --ownerpass OOO" "--take-ownership --srkpass SSS" "--take-ownership --ownerpass OO --srkpass SS" "--take-ownership --lock-nvram --display" "--display" "--lock-nvram --display" "--take-ownership --srk-well-known" "--take-ownership --owner-well-known" "--take-ownership --srk-well-known --owner-well-known" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile256bit.txt --cipher aes-256-cbc" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --cipher aes-256-cbc" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile-fd 100 --cipher aes-256-cbc" "--createek --create-ek-cert --create-platform-cert --lock-nvram --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile-fd 101 --cipher aes-256-cbc" ) # Open read-only file descriptors referenced in test cases exec 100<${TESTDIR}/data/keyfile256bit.txt exec 101<${TESTDIR}/data/pwdfile.txt FILESIZES=( 1185 1605 2066 1605 2066 1185 2066 2066 2066 2066 1185 1185 2066 2066 2066 1721 1788 1788 1820 1820 1820 1820 ) source ${TESTDIR}/common SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} TPMDIR=$(mktemp -d) SWTPM_SETUP_CONF=$SRCDIR/etc/swtpm_setup.conf # filesystem privileges require to run swtpm_setup as root during test TPMAUTHORING="$ROOT/src/swtpm_setup/swtpm_setup --config ${SWTPM_SETUP_CONF}" PATH=${ROOT}/src/swtpm_bios:${TESTDIR}:$PATH trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR } # swtpm_setup.conf points to the local create_certs.sh # For create_certs.sh to be found (with out full path) # add this directory to the PATH PATH=$PATH:$PWD for (( i=0; i<${#PARAMETERS[*]}; i++)); do rm -rf $TPMDIR/* echo -n "Test $i: " $TPMAUTHORING \ --tpm-state $TPMDIR \ --tpm "$SWTPM_EXE socket ${SWTPM_TEST_SECCOMP_OPT}" \ ${PARAMETERS[$i]} 2>&1 >/dev/null if [ $? -ne 0 ]; then echo "ERROR: Test with parameters '${PARAMETERS[$i]}' failed." exit 1 elif [ ! -f $TPMDIR/tpm-00.permall ]; then echo "ERROR: Test with parameters '${PARAMETERS[$i]}' did not produce file $TPMDIR/tpm-00.permall." exit 1 fi FILESIZE=$(get_filesize $TPMDIR/tpm-00.permall) if [ ${FILESIZE} -ne ${FILESIZES[$i]} ]; then echo "ERROR: Unexpected file size of $FILESIZE, "\ "expected ${FILESIZES[$i]}. Parameters: ${PARAMETERS[$i]}" exit 1 fi # Make sure the state is encrypted when a key was given. # We expect sequences of 4 0-bytes in unencrypted state # and no such sequences in encrypted state. nullseq="$(cat $TPMDIR/tpm-00.permall | \ od -t x1 -A n | tr -d '\n' | tr -s ' ' | grep "00 00 00 00")" if [[ "${PARAMETERS[$i]}" =~ (keyfile|pwdfile) ]]; then if [ -n "${nullseq}" ]; then echo "ERROR: State file is not encrypted with" \ "parameters '${PARAMETERS[$i]}'" fi else if [ -z "${nullseq}" ]; then echo "ERROR: State must not be encrypted with" \ "parameters '${PARAMETERS[$i]}'" fi fi echo "SUCCESS with parameters '${PARAMETERS[$i]}'." done exec 100>&- exec 101>&- exit 0 swtpm-0.6.3/tests/test_print_capabilities000077500000000000000000000004161421141172300206630ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IFACE=cuse bash _test_print_capabilities ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IFACE=socket bash _test_print_capabilities ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_resume_volatile000077500000000000000000000015301421141172300202130ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65414 export SWTPM_CTRL_PORT=65415 bash _test_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65414 bash _test_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_samples_create_tpmca000077500000000000000000000221431421141172300211720ustar00rootroot00000000000000#!/usr/bin/env bash #set -x # For the license, see the LICENSE file in the root directory. if [ "$(id -u)" -ne 0 ]; then echo "Need to be root to run this test." exit 77 fi # tpmtool is not packaged everywhere ... if [ -z "$(type -P tpmtool)" ]; then echo "Could not find tpmtool in PATH" exit 77 fi ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..} PATH=$ROOT/src/swtpm:$PATH source ${abs_top_builddir:-$(dirname "$0")/..}/tests/test_config SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca SWTPM_LOCALCA=${ROOT}/samples/swtpm-localca SWTPM=${ROOT}/src/swtpm/swtpm SWTPM_IOCTL=${ROOT}/src/swtpm_ioctl/swtpm_ioctl SWTPM_INTERFACE=socket+socket SWTPM_SERVER_NAME=localhost SWTPM_SERVER_PORT=65434 SWTPM_CTRL_PORT=65435 TCSD_LISTEN_PORT=65436 SRK_PASSWORD=srk OWNER_PASSWORD=owner workdir=$(mktemp -d) TCSD_CONF=${workdir}/tcsd.conf TCSD_SYSTEM_PS_FILE=${workdir}/system_ps_file TCSD_PIDFILE=${workdir}/tcsd.pid SWTPM_LOCALCA_DIR="${workdir}/my localca" SWTPM_LOCALCA_CONF="${workdir}/my localca/swtpm-localca.conf" # Captured TCSD file when using a SRK_PASSWORD=srk TCSD_FILE="AQEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAABLwEAAAAAAwAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAQEAAAARAAAAAAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAA AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" function cleanup() { if [ -n "${TCSD_PID}" ]; then kill_quiet -15 ${TCSD_PID} fi if [ -n "${SWTPM_PID}" ]; then kill_quiet -9 ${SWTPM_PID} fi if [ -n "${BASH_PID}" ]; then kill_quiet -9 ${BASH_PID} fi rm -rf "${workdir}" } trap "cleanup" SIGTERM EXIT source ${TESTDIR}/common PATH=${ROOT}/src/swtpm_bios:${ROOT}/src/swtpm_cert:${PATH} # run the test with the given owner and SRK passwords # @param1: owner password; empty means to use well known password # @param2: SRK password; empty means to use well known password # @param3: vTPM is a TPM 2.0 function run_test() { local owner_password="$1" local srk_password="$2" local vtpm_is_tpm2="$3" local params certinfo regex regexs fil i skip rm -rf "${workdir}"/* cat <<_EOF_ > "${workdir}/swtpm_setup.conf" create_certs_tool=${SWTPM_LOCALCA} create_certs_tool_config=${workdir}/swtpm-localca.conf create_certs_tool_options=/dev/null _EOF_ params="" if [ -n "${owner_password}" ]; then params="${params} --ownerpass ${owner_password}" else params="${params} --owner-well-known" fi params="${params} --srkpass ${srk_password}" # First setup the TPM and take ownership of it and set SRK password $SWTPM_SETUP \ --runas root \ --tpm-state "${workdir}" \ --logfile "${workdir}/logfile" \ --config "${workdir}/swtpm_setup.conf" \ --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ --take-ownership \ ${params} >/dev/null if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi echo "Successfully took ownership of TPM and set owner and SRK passwords." run_swtpm ${SWTPM_INTERFACE} \ --flags not-need-init \ --tpmstate "dir=${workdir}" swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Startup the TPM res="$(swtpm_cmd_tx "${SWTPM_INTERFACE}" '\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01')" exp=' 00 c4 00 00 00 0a 00 00 00 00' if [ "$res" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(ST_Clear)" echo "expected: $exp" echo "received: $res" exit 1 fi echo "$TCSD_FILE" | base64 -d > "${TCSD_SYSTEM_PS_FILE}" # Setup the TCSD config file and start TCSD with it cat <<_EOF_ > "${TCSD_CONF}" port = ${TCSD_LISTEN_PORT} system_ps_file = ${TCSD_SYSTEM_PS_FILE} _EOF_ # Due to recent changes in tcsd we have to try with TSS_USER=tss and TSS_USER=root # Before the following worked: # - tss:tss 0600 for TSS_USER=tss and TSS_GROUP=tss # - root:tss 0640 for TSS_USER=root and TSS_GROUP=tss # After the changes: # - root:tss 0640 for TSS_USER=tss and TSS_GROUP=tss while :; do chown ${TSS_USER}:${TSS_GROUP} "${TCSD_CONF}" if [ "${TSS_USER}" == "${TSS_GROUP}" ]; then chmod 0600 "${TCSD_CONF}" else chmod 0640 "${TCSD_CONF}" fi bash -c "TCSD_USE_TCP_DEVICE=1 TCSD_TCP_DEVICE_PORT=${SWTPM_SERVER_PORT} tcsd -c "${TCSD_CONF}" -e -f &>/dev/null & echo \$! > "${TCSD_PIDFILE}"; wait" & BASH_PID=$! if wait_for_file "${TCSD_PIDFILE}" 3; then echo "Error: Could not get TCSD's PID file" exit 1 fi # wait for PID to be written sleep 0.5 TCSD_PID=$(cat "${TCSD_PIDFILE}") kill_quiet -0 "${TCSD_PID}" if [ $? -ne 0 ]; then # Try again with root unless we already tried if [ "$TSS_USER" != "root" ]; then TSS_USER="root" continue fi echo "Error: TCSD with pid ${TCSD_PID} must have terminated" exit 1 fi break done ${SWTPM_CREATE_TPMCA} \ --dir "${SWTPM_LOCALCA_DIR}" \ --srk-password "${srk_password}" \ --register \ --group "${TSS_GROUP}" \ --tss-tcsd-port "${TCSD_LISTEN_PORT}" \ --outfile "${SWTPM_LOCALCA_CONF}" &>/dev/null if [ $? -ne 0 ]; then echo "Error: Could not create TPM CA" exit 1 fi for fil in \ swtpm-localca-rootca-cert.pem \ swtpm-localca-rootca-privkey.pem \ swtpm-localca-tpmca-cert.pem \ swtpm-localca-tpmca-pubkey.pem; do if [ ! -r "${SWTPM_LOCALCA_DIR}/${fil}" ]; then echo "Error: TPM CA tool did not create file ${fil}." exit 1 fi done params="" if [ -n "${srk_password}" ]; then params="^parentkey_password =" fi for regex in \ "^statedir = " \ "^signingkey = " \ "^issuercert = " \ "^certserial = " \ "^TSS_TCSD_HOSTNAME = " \ "^TSS_TCSD_PORT = " \ ${params}; do if [ -n "${regex}" ] && \ [ -z "$(grep -E "${regex}" "${SWTPM_LOCALCA_CONF}")" ]; then echo "Error: Could not find regex '${line}' in CA config file." cat "${SWTPM_LOCALCA_CONF}" exit 1 fi done params="" if [ ${vtpm_is_tpm2} -ne 0 ]; then params="--tpm2" skip=0 else skip=7 # header in cert fi # make sure we can actually sign with this new certificate ${SWTPM_LOCALCA} \ --type ek \ --ek x=739192d8f1004283957a7b1568d610b41c637ccc114aadcac4908c20456468fa,y=59f63ac06f8011f6fdd1460c6bc8e3e0a2d090d4fc188c7e04870e06795ce8ae \ --dir "${workdir}" --vmid test \ ${params} \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \ --tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM \ --configfile "${SWTPM_LOCALCA_CONF}" \ --optsfile /dev/null if [ $? -ne 0 ]; then echo "Error: The CA could not sign with the new certificate" exit 1 fi if [ ! -f "${workdir}/ek.cert" ]; then echo "Error: The CA did not produce a certificate" exit 1 fi # cert was for example 541 bytes long if [ $(get_filesize "${workdir}/ek.cert") -lt 500 ]; then echo "Error: The certificate's size is dubious" ls -l "${workdir}/ek.cert" exit 1 fi # Check the contents of the certificate certinfo=$(dd "if=${workdir}/ek.cert" bs=1 "skip=$skip" status=none | \ "$CERTTOOL" -i --inder) regexs=('^[[:space:]]+2.23.133.8.1$' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.3=.*' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.2=.*' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.1=.*' '^[[:space:]]+Certificate Authority \(CA\): FALSE$' '^[[:space:]]+Unknown extension 2.5.29.9 \(not critical\):$' '^[[:space:]]+Hexdump: 3019301706056781050210310e300c0c03322e3002010002020092$') if [ ${vtpm_is_tpm2} -ne 0 ]; then # TPM 2.0; due to ecc: Key agreement regexs+=('^[[:space:]]+Key agreement\.$' '^[[:space:]]+Signature Algorithm: RSA-SHA256$') else regexs+=('^[[:space:]]+Key encipherment\.$' '^[[:space:]]+Signature Algorithm: RSA-SHA1$') fi for ((i=0; i < ${#regexs}; i++)); do \ if [ -n "${regexs[$i]}" ] && \ [ -z "$(echo "${certinfo}" | grep -E "${regexs[$i]}")" ]; then echo "Error: Could not match regex '${regexs[$i]}' with certificate info:" echo "${certinfo}" exit 1 fi done # Send SIGTERM to TCSD kill_quiet -15 "${TCSD_PID}" # Shut down TPM run_swtpm_ioctl "${SWTPM_INTERFACE}" -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone "${SWTPM_PID}" 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if wait_process_gone "${SWTPM_PID}" 4; then echo "Error: tcsd should not be running anymore." exit 1 fi } # run_test run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 1 echo "Test 1: OK" run_test "${OWNER_PASSWORD}" "${SRK_PASSWORD}" 0 echo "Test 2: OK" run_test "" "${SRK_PASSWORD}" 1 echo "Test 3: OK" run_test "" "${SRK_PASSWORD}" 0 echo "Test 4: OK" exit 0 swtpm-0.6.3/tests/test_save_load_encrypted_state000077500000000000000000000016121421141172300222270ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65416 export SWTPM_CTRL_PORT=65417 bash _test_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65416 bash _test_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_save_load_state000077500000000000000000000015301421141172300201510ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65418 export SWTPM_CTRL_PORT=65419 bash _test_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65418 bash _test_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_setbuffersize000077500000000000000000000015161421141172300177000ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65432 export SWTPM_CTRL_PORT=65433 bash _test_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65432 bash _test_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_setdatafd.py000077500000000000000000000053071421141172300174100ustar00rootroot00000000000000#!/usr/bin/env python3 import os import sys import socket import subprocess import time import struct from array import array if sys.version_info[0] < 3: import twisted.python.sendmsg as sendmsg def toString(arr): return ' '.join('{:02x}'.format(x) for x in arr) def test_ReadPCR10(fd): send_data = bytearray(b"\x00\xC1\x00\x00\x00\x0C\x00\x00\x00\x99\x00\x01") exp_data = bytearray([0x00, 0xC4, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x26]) try: print("Sending data over ....") n = fd.send(send_data) print("Written %d bytes " % n) except socket.error as e: print("SocketError") fd.close() return False buf = fd.recv(1024) fd.close() if buf: if bytearray(buf) == exp_data: return True else: print("Unexpected reply:\n actual: %s\n expected: %s" % (toString(buf), toString(exp_data))) return False else: print("Null reply from swtpm") return False def test_SetDatafd(): fd, _fd = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM) sock_path = os.getenv('SOCK_PATH') cmd_set_data_fd = bytearray([0x00, 0x00, 0x00, 0x10]) expected_res = bytearray([0x00, 0x00, 0x00, 0x00]) try: fds = array("i") fds.append(_fd.fileno()) ctrlfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) print("Connecting to server at : %s" % sock_path) ctrlfd.connect(sock_path) print("Sending data fd over ctrl fd...") if sys.version_info[0] < 3: sendmsg.send1msg(ctrlfd.fileno(), str(cmd_set_data_fd), 0, [(socket.SOL_SOCKET, sendmsg.SCM_RIGHTS, struct.pack("i", _fd.fileno()))]) else: ctrlfd.sendmsg([cmd_set_data_fd], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fds)]) except socket.error as e: print("SocketError: " + str(e)) ctrlfd.close() buf = ctrlfd.recv(4) print("Received bytes.. : %s" % buf) if buf: caps = bytearray(buf) if caps == expected_res: return test_ReadPCR10(fd) else: print("Unexpected reply for CMD_SET_DATA_FD: \n" " actual: %s\n expected: %s" % (toString(caps), toString(expected_res))) return False else: print("Null reply from swtpm") return False if __name__ == "__main__": try: if not test_SetDatafd(): res = 1 else: res = 0 except: print("__Exception: ", sys.exc_info()) res = -1 sys.exit(res) swtpm-0.6.3/tests/test_swtpm_bios000077500000000000000000000014771421141172300172140ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65424 export SWTPM_CTRL_PORT=65425 bash _test_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65424 bash _test_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_swtpm_cert000077500000000000000000000104671421141172300172140ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} SWTPM_CERT=${SWTPM_CERT:-${ROOT}/src/swtpm_cert/swtpm_cert} cert=$(mktemp) pwdfile=$(mktemp) trap "cleanup" SIGTERM EXIT function cleanup() { rm -f "${cert}" "${pwdfile}" } function check_cert_size() { local cert="$1" local exp="$2" # Unfortunately different GnuTLS versions may create certs of different # sizes; deactivate this test for now return local size=$(stat -c%s ${cert} 2>/dev/null) if [ $size -ne $exp ]; then echo "Warning: Certificate file has unexpected size." echo " Expected: $exp; found: $size" fi } VARNAME=password ${SWTPM_CERT} \ --signkey ${TESTDIR}/data/signkey-encrypted.pem \ --signkey-pwd env:VARNAME \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \ --days 3650 \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 1.2 --tpm-spec-revision 123 --tpm-spec-level 321 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1224 # truncate result file echo -n > ${cert} echo "Test 1: OK" ${SWTPM_CERT} \ --signkey ${TESTDIR}/data/signkey-encrypted.pem \ --signkey-pwd file:<(echo -en "password") \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 1.2 --tpm-spec-revision 123 --tpm-spec-level 321 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1302 # truncate result file echo -n > ${cert} echo "Test 2: OK" ${SWTPM_CERT} \ --signkey ${TESTDIR}/data/signkey-encrypted.pem \ --signkey-pwd pass:password \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --pubkey ${TESTDIR}/data/pubek.pem \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 1.2 --tpm-spec-revision 123 --tpm-spec-level 321 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1367 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 3: OK" ###################### Platform Certificate ##################### echo -en "password" > ${pwdfile} exec 100<${pwdfile} ${SWTPM_CERT} \ --type platform \ --signkey ${TESTDIR}/data/signkey-encrypted.pem \ --signkey-pwd fd:100 \ --issuercert ${TESTDIR}/data/issuercert.pem \ --pubkey ${TESTDIR}/data/pubek.pem \ --out-cert ${cert} \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --platform-manufacturer Fedora \ --platform-model QEMU \ --platform-version 2.1 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1411 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 4: OK" swtpm-0.6.3/tests/test_swtpm_setup_create_cert000077500000000000000000000052161421141172300217530ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..} PATH=$ROOT/src/swtpm:$PATH SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup SWTPM_LOCALCA=${ROOT}/samples/swtpm-localca SWTPM=${ROOT}/src/swtpm/swtpm workdir=$(mktemp -d) SIGNINGKEY=${workdir}/signingkey.pem ISSUERCERT=${workdir}/issuercert.pem CERTSERIAL=${workdir}/certserial PATH=${ROOT}/src/swtpm_bios:$PATH trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf ${workdir} } # We want swtpm_cert to use the local CA and see that the # local CA script automatically creates a signingkey and # self-signed certificate; use ${WORKDIR} in the config files # to test env variable resolution cat <<_EOF_ > ${workdir}/swtpm-localca.conf statedir=\${WORKDIR} signingkey = \${WORKDIR}/signingkey.pem issuercert = \${WORKDIR}/issuercert.pem certserial = \${WORKDIR}/certserial _EOF_ cat <<_EOF_ > ${workdir}/swtpm-localca.options --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 --platform-manufacturer Fedora --platform-version 2.1 --platform-model QEMU _EOF_ cat <<_EOF_ > ${workdir}/swtpm_setup.conf create_certs_tool=${SWTPM_LOCALCA} create_certs_tool_config=\${WORKDIR}/swtpm-localca.conf create_certs_tool_options=\${WORKDIR}/swtpm-localca.options _EOF_ # We need to adapt the PATH so the correct swtpm_cert is picked export PATH=${ROOT}/src/swtpm_cert:${PATH} # Create a ROOT CA with a password-protected private key export SWTPM_ROOTCA_PASSWORD=password # we need to create at least one cert: --create-ek-cert WORKDIR=${workdir} \ $SWTPM_SETUP \ --tpm-state ${workdir} \ --create-ek-cert \ --config ${workdir}/swtpm_setup.conf \ --logfile ${workdir}/logfile \ --tpm "${SWTPM} socket ${SWTPM_TEST_SECCOMP_OPT}" if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi if [ ! -r "${SIGNINGKEY}" ]; then echo "Error: Signingkey file ${SIGNINGKEY} was not created." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi if [ ! -r "${ISSUERCERT}" ]; then echo "Error: Issuer cert file ${ISSUERCERT} was not created." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi if [ ! -r "${CERTSERIAL}" ]; then echo "Error: Cert serial number file ${CERTSERIAL} was not created." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi if [ -z "$(grep "ENCRYPTED PRIVATE KEY" ${workdir}/swtpm-localca-rootca-privkey.pem)" ]; then echo "Error: Root CA's private key should be encrypted" cat ${workdir}/swtpm-localca-rootca-privkey.pem exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_tpm12000077500000000000000000000065101421141172300157620ustar00rootroot00000000000000#!/usr/bin/env bash if [ ${SWTPM_TEST_EXPENSIVE:-0} -eq 0 ]; then exit 77 fi ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-${PWD}/$(dirname "$0")} function cleanup() { if [ -n "${SWTPM_PID}" ]; then kill -9 ${SWTPM_PID} fi if [ -n "${SWTPM1_PID}" ]; then kill -9 ${SWTPM1_PID} fi if [ -n ${WORKDIR} ]; then rm -rf ${WORKDIR} fi # clean up after (interrupted) test suite rm -f /tmp/.key-*-0 /tmp/.delegation-0 /tmp/.transdigest-*-0 } trap "cleanup" EXIT source ${TESTDIR}/common WORKDIR=$(mktemp -d) TESTLOG=${WORKDIR}/test.log # variables used by the TPM 1.2 test suite TPM_SERVER_PORT=65440 TPM_SERVER_NAME=127.0.0.1 SLAVE_TPM_PORT=65442 SLAVE_TPM_SERVER=127.0.0.1 SWTPM_INTERFACE=socket+socket # Start main TPM 1.2 SWTPM_SERVER_PORT=${TPM_SERVER_PORT} SWTPM_SERVER_NAME=${TPM_SERVER_NAME} SWTPM_CTRL_PORT=65441 mkdir -p ${WORKDIR}/tpm12.1 SWTPM_SERVER_NO_DISCONNECT="1" run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=${WORKDIR}/tpm12.1 \ --flags not-need-init SWTPM1_PID=${SWTPM_PID} # Start 2nd TPM 1.2 SWTPM_SERVER_PORT=${SLAVE_TPM_PORT} SWTPM_SERVER_NAME=${SLAVE_TPM_SERVER} SWTPM_CTRL_PORT=65443 mkdir -p ${WORKDIR}/tpm12.2 SWTPM_SERVER_NO_DISCONNECT="1" run_swtpm ${SWTPM_INTERFACE} \ --tpmstate dir=${WORKDIR}/tpm12.2 \ --flags not-need-init pushd ${WORKDIR} &>/dev/null for ((i = 0; i < 3; i++)); do curl -sJOL https://sourceforge.net/projects/ibmswtpm/files/tpm4769tar.gz/download if [ $? -eq 0 ]; then break fi # wait 3..10 seconds for a retry sleep $((3 + (RANDOM & 7))) done hash=$(get_sha1_file tpm4769tar.gz) if [ $hash != ca99a3ccd3e41cdd9983086a9b944023b6049bbc ]; then echo "Error: Downloaded file does not have expected hash." echo "Actual: $hash" exit 1 fi tar -xzf tpm4769tar.gz pushd libtpm &>/dev/null patch -p0 < ${TESTDIR}/patches/libtpm.patch if [ $? -ne 0 ]; then echo "Error: Patching failed." exit 1 fi ./autogen LIBS="" CFLAGS="-g -O2" ./configure make -j$(nproc) pushd utils &>/dev/null # variables used by TPM 1.2 tools and test suite export TPM_SERVER_PORT=${TPM_SERVER_PORT} \ TPM_SERVER_NAME=${TPM_SERVER_NAME} \ SLAVE_TPM_PORT=${SLAVE_TPM_PORT} \ SLAVE_TPM_SERVER=${SLAVE_TPM_SERVER} \ PATH=$PWD:$PATH if wait_for_serversocket ${TPM_SERVER_PORT} 127.0.0.1 2; then echo "Error: swtpm 1 did not open port ${TPM_SERVER_PORT}" exit 1 fi if wait_for_serversocket ${SLAVE_TPM_PORT} 127.0.0.1 2; then echo "Error: swtpm 2 did not open port ${SLAVE_TPM_PORT}" exit 1 fi tpmbios ln -s makeidentity identity # keep test 1 last due to ERRORs it creates since we do not # restart the TPM for tst in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20 23 25 26 1; do TPM_AUDITING=0 TPM_TRANSPORT=0 echo "Running test ${tst}" if [[ "${tst}" =~ ^(1)$ ]]; then $SWTPM_IOCTL --tcp :65441 -i tpmbios elif [[ "${tst}" = ^25$ ]]; then TPM_AUDITING=1 TPM_TRANSPORT=1 fi timeout 40 ./test_console.sh \ --non-interactive ${tst} >> ${TESTLOG} /dev/null popd &>/dev/null echo "OK" exit 0 swtpm-0.6.3/tests/test_tpm2_ctrlchannel2000077500000000000000000000350621421141172300203440ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} SWTPM_IOCTL=${SWTPM_IOCTL:-$ROOT/src/swtpm_ioctl/swtpm_ioctl} TPMDIR=`mktemp -d` PID_FILE=$TPMDIR/${SWTPM}.pid SOCK_PATH=$TPMDIR/sock CMD_PATH=$TPMDIR/cmd RESP_PATH=$TPMDIR/resp LOGFILE=$TPMDIR/logfile VOLATILESTATE=$TPMDIR/volatile source ${TESTDIR}/common source ${TESTDIR}/test_common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } # Test 1: test the control channel on the chardev tpm if [ $(id -u) -eq 0 ]; then FOWNER=",uid=$(id -u nobody),gid=$(id -G nobody | cut -d" " -f1)" FILEOWNER="$(id -u nobody) $(id -G nobody | cut -d" " -f1)" fi # make sure --print-capabiities exits with '0' msg=$($SWTPM_EXE chardev --print-capabilities 2>&1) if [ $? -ne 0 ]; then echo "Error: swtpm chardev --print-capabilities failed" echo "$msg" exit 1 fi FILEMODE=621 # use a pseudo terminal exec 100<>/dev/ptmx $SWTPM_EXE chardev \ --fd 100 \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH,mode=${FILEMODE}${FOWNER} \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Chardev TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 act=$($SWTPM_IOCTL --unix $SOCK_PATH -c 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CAPABILITY failed: $act" exit 1 fi filemode=$(get_filemode $SOCK_PATH) if [ "$filemode" != "$FILEMODE" ]; then echo "Filemode bits are wrong" echo "Expected: $FILEMODE" echo "Actual : $filemode" exit 1 fi fileowner=$(get_fileowner $SOCK_PATH) if [ -n "$FILEOWNER" ] && [ "$fileowner" != "$FILEOWNER" ]; then echo "File ownership is wrong" echo "Expected: $FILEOWNER" echo "Actual : $fileowner" exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send TPM_Init to the TPM: CMD_INIT = 0x00 00 00 02 + flags act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi if [ ! -r $TPMDIR/tpm2-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f act=$($SWTPM_IOCTL --unix $SOCK_PATH -g 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CONFIG failed: $act" exit 1 fi exp="ptm configuration flags: 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi echo "OK" # Test 2: test the control channel on the socket tpm # There are a few more tests here that require sending commands to the TPM # use a pseudo terminal $SWTPM_EXE socket \ --server port=65532,disconnect=true \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ --flags startup-clear \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE exec 100<>/dev/tcp/localhost/65532 # Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01 act=$($SWTPM_IOCTL --unix $SOCK_PATH -c 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CAPABILITY failed: $act" exit 1 fi exp="ptm capability is 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Startup the TPM; we used --flags startup-clear so expect this to fail now with 0x100 echo -en '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00' >&100 RES=$(cat <&100 | od -t x1 -A n) exp=' 80 01 00 00 00 0a 00 00 01 00' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_Startup(SU_Clear)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Save the volatile state: CMD_STORE_VOLATILE = 0x00 00 00 0a act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi if [ ! -r $TPMDIR/tpm2-00.volatilestate ]; then echo "Error: Socket TPM: Did not write volatile state file" exit 1 fi # 1. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 0" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # 2. Hash the given data data="a" while [ ${#data} -lt $((0x2000)) ]; do data="${data}${data}" done act=$($SWTPM_IOCTL --unix $SOCK_PATH -h $data 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL data hashing failed: $act" exit 1 fi # 3. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 1" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # 4. Send command to reset TPM established flag: CMD_RESET_TPMESTABLISHED = 00 00 00 0b 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -r 3 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_RESET_TPMESTABLISHED failed: $act" exit 1 fi # 5. Send command to get TPM established flag: CMD_GET_TPMESTABLISHED = 00 00 00 04 act=$($SWTPM_IOCTL --unix $SOCK_PATH -e 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_TPMESTABLISHED failed: $act" exit 1 fi exp="tpmEstablished is 0" if [ "$act" != "$exp" ]; then echo "Error: Expected '$exp' but got '$act'." exit 1 fi # Read PCR 17 exec 100<>/dev/tcp/localhost/65532 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02' >&100 RES=$(cat <&100 | od -t x1 -A n | tr -d "\n") exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 18 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 e5 17 e3 9b 10 a3 5b 3b b7 29 95 79 4b c6 4a 07 f8 bc b0 bd e6 bb 31 ad 35 27 fb 6f 64 f8 4c b9' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c act=$($SWTPM_IOCTL --unix $SOCK_PATH --save volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_STATEBLOB failed: $act" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Read PCR 17 -- should fail now exec 100<>/dev/tcp/localhost/65532 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02' >&100 RES=$(cat <&100 | od -t x1 -A n | tr -d "\n") exp=' 80 01 00 00 00 0a 00 00 01 01' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send get config command to the TPM: CMD_GET_CONFIG = 00 00 00 0f act=$($SWTPM_IOCTL --unix $SOCK_PATH -g 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_CONFIG failed: $act" exit 1 fi exp="ptm configuration flags: 0x([[:xdigit:]]+)" if ! [[ "$act" =~ ^${exp}$ ]]; then echo "Error: Expected string following regular expression '$exp' from ioctl tool but got '$act'." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi echo "OK" # Test 3: test the control channel on the socket tpm: resume encrypted state # copy all the state files cp ${TESTDIR}/data/tpm2state2/* ${TPMDIR} $SWTPM_EXE socket \ --server port=65532,disconnect=true \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --key pwdfile=${TESTDIR}/data/tpm2state2/pwdfile.txt,kdf=sha512 \ --tpm2 \ --flags not-need-init \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 exec 100<>/dev/tcp/localhost/65532 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Get the volatile state of the TPM: CMD_GET_STATEBLOB = 00 00 00 0c rm -f $VOLATILESTATE act=$($SWTPM_IOCTL --unix $SOCK_PATH --save volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_GET_STATEBLOB failed: $act" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi if [ -f $PID_FILE ]; then echo "Error: Socket TPM should have removed the PID file." exit 1 fi # remove volatile state rm -f $TPMDIR/*.volatilestate $SWTPM_EXE socket \ --server port=65532,disconnect=true \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --key pwdfile=${TESTDIR}/data/tpm2state2/pwdfile.txt,kdf=sha512 \ --tpm2 \ --flags not-need-init \ ${SWTPM_TEST_SECCOMP_OPT} & PID=$! if wait_for_file $PID_FILE 3; then echo "Error: Socket TPM did not write pidfile." exit 1 fi validate_pidfile $PID $PID_FILE # Read PCR 10 -- this should fail now exec 100<>/dev/tcp/localhost/65532 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 80 01 00 00 00 0a 00 00 01 00' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send stop command to the TPM: CMD_STOP = 00 00 00 0e act=$($SWTPM_IOCTL --unix $SOCK_PATH --stop 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STOP failed: $act" exit 1 fi # Send the volatile state to the TPM (while it is stopped) act=$($SWTPM_IOCTL --unix $SOCK_PATH --load volatile $VOLATILESTATE 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SET_STATEBLOB failed: $act" exit 1 fi # Send init command to the TPM: CMD_INIT = 00 00 00 02 act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # Read PCR 10 -- has to return same result as before exec 100<>/dev/tcp/localhost/65532 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x04\x00' >&100 RES=$(cat <&100 | od -t x1 -A n -w128) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 16 00 00 00 01 00 0b 03 00 04 00 00 00 00 01 00 20 f6 85 98 e5 86 8d e6 8b 97 29 99 60 f2 71 7d 17 67 89 a4 2f 9a ae a8 c7 b7 aa 79 a8 62 56 c1 de' if [ "$RES" != "$exp" ]; then echo "Error: (1) Did not get expected result from TPM2_PCRRead(10)" echo "expected: $exp" echo "received: $RES" exit 1 fi # Reset PCR 20 while in locality 0 -- should not work exec 100<>/dev/tcp/localhost/65532 echo -en '\x80\x02\x00\x00\x00\x1b\x00\x00\x01\x3d\x00\x00\x00\x14\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00' >&100 RES=$(cat <&100 | od -t x1 -A n) exp=' 80 01 00 00 00 0a 00 00 09 07' if [ "$RES" != "$exp" ]; then echo "Error: Trying to reset PCR 20 in locality 0 returned unexpected result" echo "expected: $exp" echo "received: $RES" exit 1 fi # In locality 2 we can reset PCR 20 # Set the locality on the TPM: CMD_SET_LOCALITY = 00 00 00 05 act=$($SWTPM_IOCTL --unix $SOCK_PATH -l 2 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SET_LOCALITY failed: $act" exit 1 fi # Reset PCR 20 while in locality 2 -- has to work exec 100<>/dev/tcp/localhost/65532 echo -en '\x80\x02\x00\x00\x00\x1b\x00\x00\x01\x3d\x00\x00\x00\x14\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00' >&100 RES=$(cat <&100 | od -t x1 -A n -w512) exp=' 80 02 00 00 00 13 00 00 00 00 00 00 00 00 00 00 01 00 00' if [ "$RES" != "$exp" ]; then echo "Error: Could not reset PCR 20 in locality 2" echo "expected: $exp" echo "received: $RES" exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_tpm2_derived_keys000077500000000000000000000014701421141172300204360ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_derived_keys ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_derived_keys ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65444 export SWTPM_CTRL_PORT=65445 bash _test_tpm2_derived_keys ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+socket export SWTPM_CTRL_PORT=65445 bash _test_tpm2_derived_keys ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_derived_keys ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_encrypted_state000077500000000000000000000015611421141172300211570ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65534 export SWTPM_CTRL_PORT=65535 bash _test_tpm2_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65534 bash _test_tpm2_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_getcap000077500000000000000000000015041421141172300172220ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65506 export SWTPM_CTRL_PORT=65507 bash _test_tpm2_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65506 bash _test_tpm2_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_getcap ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_hashing000077500000000000000000000015111421141172300173760ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65514 export SWTPM_CTRL_PORT=65515 bash _test_tpm2_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65514 bash _test_tpm2_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_hashing ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_hashing2000077500000000000000000000015161421141172300174650ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65516 export SWTPM_CTRL_PORT=65517 bash _test_tpm2_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65516 bash _test_tpm2_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_hashing2 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_hashing3000077500000000000000000000015161421141172300174660ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing3 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_hashing3 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65518 export SWTPM_CTRL_PORT=65519 bash _test_tpm2_hashing3 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65518 bash _test_tpm2_hashing3 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_hashing3 ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_ibmtss2000077500000000000000000000066661421141172300173600ustar00rootroot00000000000000#!/usr/bin/env bash if [ ${SWTPM_TEST_EXPENSIVE:-0} -eq 0 ]; then exit 77 fi ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} ABSTESTDIR=$(cd ${TESTDIR} &>/dev/null;echo ${PWD}) PATCHESDIR=${ABSTESTDIR}/patches SWTPM_SERVER_PORT=65426 SWTPM_SERVER_NAME=127.0.0.1 SWTPM_CTRL_PORT=65427 SWTPM_INTERFACE=socket+socket function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi if [ -n ${WORKDIR} ]; then rm -rf ${WORKDIR} fi } trap "cleanup" EXIT source ${TESTDIR}/common WORKDIR=$(mktemp -d) REGLOG=${WORKDIR}/reglog SWTPM_SERVER_NO_DISCONNECT="1" run_swtpm ${SWTPM_INTERFACE} \ --tpm2 \ --tpmstate dir=${WORKDIR} \ --flags not-need-init pushd ${WORKDIR} &>/dev/null git clone https://git.code.sf.net/p/ibmtpm20tss/tss ibmtpm20tss-tss pushd ibmtpm20tss-tss &>/dev/null git checkout tags/v1.6.0 if [ $? -ne 0 ]; then echo "'Git checkout' failed." exit 1 fi # To be able to apply the patches we need to to set some variables # for user that don't have this set up properly git config --local user.name test git config --local user.email test@test.test # A v1.6.0 bug work-around: # We cannot run the EK certificate tests since rootcerts.txt points to # files we do not have git am < ${PATCHESDIR}/0001-Deactivate-test-cases-accessing-rootcerts.txt.patch # Implement 'powerup' for swtpm git am < ${PATCHESDIR}/0002-Implement-powerup-for-swtpm.patch # set CRYPTOLIBRARY=openssl git am < ${PATCHESDIR}/0003-Set-CRYPTOLIBRARY-to-openssl.patch # Store and restore volatile state at every step git am < ${PATCHESDIR}/0004-Store-and-restore-volatile-state-at-every-step.patch # Disable 'Events' test git am < ${PATCHESDIR}/0005-Disable-tests-related-to-events.patch rsa3072=$(run_swtpm_ioctl ${SWTPM_INTERFACE} --info 4 | sed -n 's/.*"RSAKeySizes":\[\([0-9,]*\)\].*/\1/p' | grep 3072) if [ -z "$rsa3072" ]; then echo "Modifying test cases related to RSA 3072 keys." git am < ${PATCHESDIR}/0006-Disable-testing-with-RSA-3072.patch else echo "swtpm/libtpms support RSA 3072 bit keys" fi # Adjust test suite to TPM 2.0 revision libtpms is implementing revision=$(run_swtpm_ioctl ${SWTPM_INTERFACE} --info 1 | sed 's/.*,"revision":\([^\}]*\).*/\1/') echo "Libtpms implements TPM 2.0 revision ${revision}." if [ $revision -lt 155 ]; then echo "Removing revision 155 and later test cases." git am < ${PATCHESDIR}/0007-Disable-rev155-test-cases.patch git am < ${PATCHESDIR}/0008-Disable-x509-test-cases.patch git am < ${PATCHESDIR}/0009-Disable-getcapability-TPM_CAP_ACT.patch fi autoreconf --force --install unset CFLAGS LDFLAGS LIBS ./configure --disable-tpm-1.2 make -j4 pushd utils export TPM_SERVER_NAME=127.0.0.1 export TPM_INTERFACE_TYPE=socsim export TPM_COMMAND_PORT=${SWTPM_SERVER_PORT} export TPM_PLATFORM_PORT=${SWTPM_CTRL_PORT} export SWTPM_IOCTL ./startup if [ $? -ne 0 ]; then echo "Startup of TPM2 failed" exit 1 fi ./reg.sh -a 2>&1 | tee ${REGLOG} ret=0 if [ -n "$(grep -E "^ ERROR:" ${REGLOG})" ]; then echo "There were test failures running the IBM TSS 2 tests" grep -E "^ ERROR:" ${REGLOG} -B2 -A2 ret=1 fi # Shut down run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." ret=1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." ret=1 fi popd &>/dev/null popd &>/dev/null popd &>/dev/null [ $ret -eq 0 ] && echo "OK" exit $retswtpm-0.6.3/tests/test_tpm2_init000077500000000000000000000014721421141172300167260ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65508 export SWTPM_CTRL_PORT=65509 bash _test_tpm2_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65508 bash _test_tpm2_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_init ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_locality000077500000000000000000000015161421141172300176020ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65510 export SWTPM_CTRL_PORT=65511 bash _test_tpm2_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65510 bash _test_tpm2_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_locality ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_migration_key000077500000000000000000000015421421141172300206220ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65500 export SWTPM_CTRL_PORT=65501 bash _test_tpm2_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65500 bash _test_tpm2_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_migration_key ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_parameters000077500000000000000000000154401421141172300201260ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..} PATH=$ROOT/src/swtpm:$PATH source ${abs_top_builddir:-$(dirname "$0")/..}/tests/test_config PARAMETERS=( "" "--createek" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt" "--createek --allow-signing" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile256bit.txt --cipher aes-256-cbc" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --cipher aes-256-cbc" "--ecc --createek" "--ecc --createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display" "--ecc --createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt" "--ecc --createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt" "--ecc --createek --allow-signing" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile256bit.txt --cipher aes-256-cbc" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --cipher aes-256-cbc" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile-fd 100 --cipher aes-256-cbc" "--ecc --createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile-fd 101 --cipher aes-256-cbc" ) # Tests for 3072 bit RSA keys to be appended to above array if RSA 3072 keys are supported PARAMETERS_3072=( "--createek --rsa-keysize 3072" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --rsa-keysize 3072" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt --rsa-keysize 3072" "--createek --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --rsa-keysize 3072" "--createek --allow-signing --rsa-keysize 3072" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --rsa-keysize 3072" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile.txt --rsa-keysize 3072" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --rsa-keysize 3072" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --keyfile ${TESTDIR}/data/keyfile256bit.txt --cipher aes-256-cbc --rsa-keysize 3072" "--createek --allow-signing --create-ek-cert --create-platform-cert --config ${TESTDIR}/swtpm_setup.conf --vmid test --display --pwdfile ${TESTDIR}/data/pwdfile.txt --cipher aes-256-cbc --rsa-keysize 3072" ) # Open read-only file descriptors referenced in test cases exec 100<${TESTDIR}/data/keyfile256bit.txt exec 101<${TESTDIR}/data/pwdfile.txt # produced file size is always the same with TPM2 SWTPM=swtpm SWTPM_EXE=$ROOT/src/swtpm/$SWTPM TPMDIR=$(mktemp -d) SWTPM_SETUP_CONF=$SRCDIR/etc/swtpm_setup.conf TPMAUTHORING="$ROOT/src/swtpm_setup/swtpm_setup --tpm2 --config ${SWTPM_SETUP_CONF}" PATH=${ROOT}/src/swtpm_bios:$PATH trap "cleanup" SIGTERM EXIT function cleanup() { if [ -n "$TPMDIR" ]; then rm -rf $TPMDIR fi } if [ -n "$($TPMAUTHORING --tpm2 --print-capabilities | grep tpm2-rsa-keysize-3072 )" ]; then PARAMETERS+=( "${PARAMETERS_3072[@]}" ) fi # swtpm_setup.conf points to the local create_certs.sh # For create_certs.sh to be found (with out full path) # add this directory to the PATH PATH=$PATH:$TESTDIR for (( i=0; i<${#PARAMETERS[*]}; i++)); do rm -rf $TPMDIR/* echo -n "Test $i: " $TPMAUTHORING \ --tpm-state $TPMDIR \ --tpm "$SWTPM_EXE socket ${SWTPM_TEST_SECCOMP_OPT}" \ ${PARAMETERS[$i]} 2>&1 >/dev/null if [ $? -ne 0 ]; then echo "ERROR: Test with parameters '${PARAMETERS[$i]}' failed." exit 1 elif [ ! -f $TPMDIR/tpm2-00.permall ]; then echo "ERROR: Test with parameters '${PARAMETERS[$i]}' did not produce file $TPMDIR/tpm2-00.permall." exit 1 fi # Make sure the state is encrypted when a key was given. # We expect sequences of 4 0-bytes in unencrypted state # and no such sequences in encrypted state. nullseq="$(cat $TPMDIR/tpm2-00.permall | \ od -t x1 -A n | tr -d '\n' | tr -s ' ' | grep "00 00 00 00")" if [[ "${PARAMETERS[$i]}" =~ (keyfile|pwdfile) ]]; then if [ -n "${nullseq}" ]; then echo "ERROR: State file is not encrypted with" \ "parameters '${PARAMETERS[$i]}'" fi else if [ -z "${nullseq}" ]; then echo "ERROR: State must not be encrypted with" \ "parameters '${PARAMETERS[$i]}'" fi fi echo "SUCCESS with parameters '${PARAMETERS[$i]}'." done exec 100>&- exec 101>&- swtpm-0.6.3/tests/test_tpm2_partial_reads000077500000000000000000000061171421141172300205760ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. # set -x cd $(dirname "$0") ROOT=${abs_top_builddir:-$(pwd)/..} export SWTPM_INTERFACE=cuse VTPM_NAME="vtpm-test-tpm2-partial-reads" SWTPM_DEV_NAME="/dev/${VTPM_NAME}" export TPM_PATH=$(mktemp -d) CMD_PATH="${TPM_PATH}/cmd" function cleanup() { pid=${SWTPM_PID} if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } function swtpm_read_n_bytes_fd100() { dd bs=1 count=$1 if=/proc/self/fd/100 2>/dev/null | \ od -t x1 -A n | \ tr -s ' ' | \ tr -d '\n' | \ sed 's/ $//g' } trap "cleanup" EXIT [ "${SWTPM_INTERFACE}" == "cuse" ] && source test_cuse source common run_swtpm ${SWTPM_INTERFACE} --tpm2 kill_quiet -0 ${SWTPM_PID} if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM did not start." exit 1 fi # Init the TPM run_swtpm_ioctl ${SWTPM_INTERFACE} -i if [ $? -ne 0 ]; then echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM." exit 1 fi kill_quiet -0 ${SWTPM_PID} 2>/dev/null if [ $? -ne 0 ]; then echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT." exit 1 fi # Prepare the TPM2_Startup echo -en '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00' > "${CMD_PATH}" swtpm_open_cmddev ${SWTPM_INTERFACE} 100 # Startup the TPM2 cat "${CMD_PATH}" >&100 # Read 4 and then 6 bytes of the response res1=$(swtpm_read_n_bytes_fd100 4) exp1=' 80 01 00 00' if [ "$res1" != "$exp1" ]; then echo "1st Startup: Unexpected 1st response part" echo "Expected: $exp1" echo "Actual : $res1" exit 1 fi res2=$(swtpm_read_n_bytes_fd100 6) exp2=' 00 0a 00 00 00 00' if [ "$res2" != "$exp2" ]; then echo "1st Startup: Unexpected 2nd response part" echo "Expected: $exp2" echo "Actual : $res2" exit 1 fi # Startup the TPM2 again (will fail, but that's ok) cat "${CMD_PATH}" >&100 # Read 4 and then only 4 bytes of the response res1=$(swtpm_read_n_bytes_fd100 4) exp1=' 80 01 00 00' if [ "$res1" != "$exp1" ]; then echo "2nd Startup: Unexpected 1st response part" echo "Expected: $exp1" echo "Actual : $res1" exit 1 fi res2=$(swtpm_read_n_bytes_fd100 4) exp2=' 00 0a 00 00' if [ "$res2" != "$exp2" ]; then echo "2nd Startup: Unexpected 2nd part" echo "Expected: $exp2" echo "Actual : $res2" exit 1 fi # Startup the TPM2 again (will fail, but that's ok) cat "${CMD_PATH}" >&100 # Read 4 and then 6 bytes of the response res1=$(swtpm_read_n_bytes_fd100 4) exp1=' 80 01 00 00' if [ "$res1" != "$exp1" ]; then echo "3rd Startup: Unexpected 1st response part" echo "Expected: $exp1" echo "Actual : $res1" exit 1 fi res2=$(swtpm_read_n_bytes_fd100 6) exp2=' 00 0a 00 00 01 00' if [ "$res2" != "$exp2" ]; then echo "3rd Startup: Unexpected 2nd part" echo "Expected: $exp2" echo "Actual : $res2" exit 1 fi run_swtpm_ioctl ${SWTPM_INTERFACE} -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone ${SWTPM_PID} 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_tpm2_print_capabilities000077500000000000000000000004301421141172300216210ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IFACE=cuse bash _test_tpm2_print_capabilities ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IFACE=socket bash _test_tpm2_print_capabilities ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_probe000077500000000000000000000014771421141172300170770ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65522 export SWTPM_CTRL_PORT=65523 bash _test_tpm2_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65522 bash _test_tpm2_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_resume_volatile000077500000000000000000000015071421141172300211610ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65502 export SWTPM_CTRL_PORT=65503 bash _test_tpm2_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+socket export SWTPM_CTRL_PORT=65503 bash _test_tpm2_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_resume_volatile ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_samples_create_tpmca000077500000000000000000000170411421141172300221350ustar00rootroot00000000000000#!/usr/bin/env bash #set -x # For the license, see the LICENSE file in the root directory. if [ "$(id -u)" -ne 0 ]; then echo "Need to be root to run this test." exit 77 fi tmp="$(getenforce 2>&1)" if [ "${tmp}" = "Enforcing" ]; then echo "Test may not work with SELinux in enforcing mode." exit 77 fi # tpm2_ptool may not be packaged everywhere ... if [ -z "$(type -P tpm2_ptool)" ]; then echo "Could not find tpm2_ptool in PATH" exit 77 fi if [ -z "$(tpm2_ptool | grep ",config,")" ]; then echo "tpm2_ptool does not support the config command" exit 77 fi if [ -z "$(type -P tpm2-abrmd)" ]; then echo "Could not find tpm2-abrmd in PATH" exit 77 fi if [ ! -r /usr/lib64/pkcs11/libtpm2_pkcs11.so ]; then echo "/usr/lib64/pkcs11/libtpm2_pkcs11.so is missing" echo "tpm2-pkcs11 package may not be installed." exit 77 fi ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:=$(dirname "$0")} SRCDIR=${abs_top_srcdir:-$(dirname "$0")/..} SWTPM_SETUP=${ROOT}/src/swtpm_setup/swtpm_setup SWTPM_CREATE_TPMCA=${SRCDIR}/samples/swtpm-create-tpmca SWTPM_LOCALCA=${SRCDIR}/samples/swtpm-localca SWTPM=${ROOT}/src/swtpm/swtpm SWTPM_IOCTL=${ROOT}/src/swtpm_ioctl/swtpm_ioctl SWTPM_INTERFACE=socket+socket SWTPM_SERVER_NAME=localhost SWTPM_SERVER_PORT=65455 SWTPM_CTRL_PORT=65454 SWTPM_FAKE_CTRL_PORT=65456 workdir=$(mktemp -d) SWTPM_LOCALCA_DIR="${workdir}/my localca" SWTPM_LOCALCA_CONF="${workdir}/my localca/swtpm-localca.conf" export TPM2_PKCS11_STORE="${workdir}" TPM2_ABRMD_PIDFILE="${workdir}/tpm2-abrmd.pid" PID="" # primary object id returned by tpm2_ptool TPM2_ABRMD_PID="" function cleanup() { if [ -n "${PID}" ]; then echo "y" | tpm2_ptool destroy ${PID} &>/dev/null fi if [ -n "${TPM2_ABRMD_PID}" ]; then kill_quiet -9 ${TPM2_ABRMD_PID} fi if [ -n "${SWTPM_PID}" ]; then kill_quiet -9 ${SWTPM_PID} fi if [ -n "${BASH_PID}" ]; then kill_quiet -9 ${BASH_PID} fi if [ -n "${NCAT_PID}" ]; then kill_quiet -9 ${NCAT_PID} fi rm -rf "${workdir}" } trap "cleanup" SIGTERM EXIT source ${TESTDIR}/common PATH=${ROOT}/src/swtpm_bios:${ROOT}/src/swtpm_cert:${PATH} # Run the tests # @param1: The vTPM for which the certificate is created is a TPM 2 function run_test() { local vtpm_is_tpm2="$1" local tmp params certinfo regex regexs fil i skip rm -rf "${workdir}"/* cat <<_EOF_ > "${workdir}/swtpm_setup.conf" create_certs_tool=${SWTPM_LOCALCA} create_certs_tool_config=${workdir}/swtpm-localca.conf create_certs_tool_options=/dev/null _EOF_ $SWTPM_SETUP \ --tpm-state "${workdir}" \ --logfile "${workdir}/logfile" \ --config "${workdir}/swtpm_setup.conf" \ --tpm "${SWTPM_EXE} socket ${SWTPM_TEST_SECCOMP_OPT}" \ --swtpm_ioctl "${SWTPM_IOCTL}" \ --tpm2 > /dev/null if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." echo "Setup Logfile:" cat ${workdir}/logfile exit 1 fi SWTPM_SERVER_NO_DISCONNECT=1 run_swtpm ${SWTPM_INTERFACE} \ --tpm2 \ --flags not-need-init \ --tpmstate "dir=${workdir}" \ --log level=0 ncat -l ${SWTPM_FAKE_CTRL_PORT} \ -k -c "xargs --null -n1 printf '\x00\x00\x00\x00' 2>/dev/null" & if [ $? -ne 0 ]; then echo "Could not start ncat" exit 1 fi NCAT_PID=$! kill_quiet -0 ${NCAT_PID} if [ $? -ne 0 ]; then echo "ncat must have terminated" exit 1 fi bash -c "tpm2-abrmd --tcti=mssim:host=127.0.0.1,port=${SWTPM_SERVER_PORT} --allow-root & echo \$! > "${TPM2_ABRMD_PIDFILE}"; wait" & BASH_PID=$! if wait_for_file "${TPM2_ABRMD_PIDFILE}" 3; then echo "Error: Could not get tpm2-abrmd's PID file" exit 1 fi TPM2_ABRMD_PID=$(cat "${TPM2_ABRMD_PIDFILE}") kill_quiet -0 "${TPM2_ABRMD_PID}" if [ $? -ne 0 ]; then echo "Error: tpm2-abrmd with pid ${TPM2_ABRMD_PID} must have terminated" exit 1 fi tmp="$(tpm2_ptool init 2>&1)" if [ $? -ne 0 ]; then echo "tpm2_ptool init failed:" echo "${tmp}" exit 1 fi PID="$(echo "${tmp}" | grep -E "^id:" |cut -d ":" -f2 | tr -d " ")" if [ -z "${PID}" ]; then echo "Could not grep the pid from the tpm2_ptool output" echo "${tmp}" exit 1 fi tmp="$(SWTPM_PKCS11_PIN="mypin 123" SWTPM_PKCS11_SO_PIN="123" ${SWTPM_CREATE_TPMCA} \ --dir "${SWTPM_LOCALCA_DIR}" \ --overwrite \ --outfile "${SWTPM_LOCALCA_CONF}" \ --group tss \ --tpm2 \ --pid "${PID}" 2>&1)" if [ $? -ne 0 ]; then echo "Error: Could not create TPM CA" echo "${tmp}" exit 1 fi for fil in \ swtpm-localca-rootca-cert.pem \ swtpm-localca-rootca-privkey.pem \ swtpm-localca-tpmca-cert.pem \ swtpm-localca-tpmca-pubkey.pem; do if [ ! -r "${SWTPM_LOCALCA_DIR}/${fil}" ]; then echo "Error: TPM CA tool did not create file ${fil}." exit 1 fi done for regex in \ "^statedir = " \ "^signingkey = " \ "^issuercert = " \ "^certserial = " \ "^SWTPM_PKCS11_PIN = mypin 123"; do if [ -n "${regex}" ] && \ [ -z "$(grep -E "${regex}" "${SWTPM_LOCALCA_CONF}")" ]; then echo "Error: Could not find regex '${line}' in CA config file." cat "${SWTPM_LOCALCA_CONF}" exit 1 fi done params="" if [ ${vtpm_is_tpm2} -ne 0 ]; then params="--tpm2" skip=0 else skip=7 # header in cert fi # make sure we can actually sign with this new certificate ${SWTPM_LOCALCA} \ --type ek \ --ek x=739192d8f1004283957a7b1568d610b41c637ccc114aadcac4908c20456468fa,y=59f63ac06f8011f6fdd1460c6bc8e3e0a2d090d4fc188c7e04870e06795ce8ae \ --dir "${workdir}" --vmid test \ ${params} \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 00 \ --tpm-model swtpm --tpm-version 20170101 --tpm-manufacturer IBM \ --configfile "${SWTPM_LOCALCA_CONF}" \ --optsfile /dev/null if [ $? -ne 0 ]; then echo "Error: The CA could not sign with the new certificate" exit 1 fi if [ ! -f "${workdir}/ek.cert" ]; then echo "Error: The CA did not produce a certificate" exit 1 fi # cert was for example 541 bytes long if [ $(get_filesize "${workdir}/ek.cert") -lt 500 ]; then echo "Error: The certificate's size is dubious" ls -l "${workdir}/ek.cert" exit 1 fi # Check the contents of the certificate certinfo=$(dd "if=${workdir}/ek.cert" bs=1 "skip=$skip" status=none | \ "$CERTTOOL" -i --inder) regexs=('^[[:space:]]+2.23.133.8.1$' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.3=.*' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.2=.*' '^[[:space:]]+directoryName:.*(,)?2.23.133.2.1=.*' '^[[:space:]]+Certificate Authority \(CA\): FALSE$' '^[[:space:]]+Unknown extension 2.5.29.9 \(not critical\):$' '^[[:space:]]+Hexdump: 3019301706056781050210310e300c0c03322e3002010002020092$') if [ ${vtpm_is_tpm2} -ne 0 ]; then # TPM 2.0; due to ecc: Key agreement regexs+=('^[[:space:]]+Key agreement\.$' '^[[:space:]]+Signature Algorithm: RSA-SHA256$') else regexs+=('^[[:space:]]+Key encipherment\.$' '^[[:space:]]+Signature Algorithm: RSA-SHA1$') fi for ((i=0; i < ${#regexs}; i++)); do \ if [ -n "${regexs[$i]}" ] && \ [ -z "$(echo "${certinfo}" | grep -E "${regexs[$i]}")" ]; then echo "Error: Could not match regex '${regexs[$i]}' with certificate info:" echo "${certinfo}" exit 1 fi done # Send SIGTERM to tpm2-abrmd kill_quiet -15 "${TPM2_ABRMD_PID}" TPM2_ABRMD_PID="" kill_quiet -9 "${NCAT_PID}" NCAT_PID="" # Shut down TPM run_swtpm_ioctl "${SWTPM_INTERFACE}" -s if [ $? -ne 0 ]; then echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM." exit 1 fi if wait_process_gone "${SWTPM_PID}" 4; then echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore." exit 1 fi if wait_process_gone "${SWTPM_PID}" 4; then echo "Error: tcsd should not be running anymore." exit 1 fi SWTPM_PID="" } # run_test run_test 1 echo "Test 1: OK" run_test 0 echo "Test 2: OK" exit 0 swtpm-0.6.3/tests/test_tpm2_samples_swtpm_localca000077500000000000000000000110341421141172300223320ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x TOPBUILD=${abs_top_builddir:-$(dirname "$0")/..} TOPSRC=${abs_top_srcdir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM_LOCALCA=${TOPBUILD}/samples/swtpm-localca workdir=$(mktemp -d "/tmp/path with spaces.XXXXXX") ek="80" # 2048 bit key must have highest bit set for ((i = 1; i < 256; i++)); do ek="${ek}$(printf "%02x" $i)" done SIGNINGKEY=${workdir}/signingkey.pem ISSUERCERT=${workdir}/issuercert.pem CERTSERIAL=${workdir}/certserial PATH=${TOPBUILD}/src/swtpm_cert:$PATH source ${TESTDIR}/common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf "${workdir}" } cat <<_EOF_ > "${workdir}/swtpm-localca.conf" statedir=${workdir} signingkey = ${SIGNINGKEY} issuercert = ${ISSUERCERT} certserial = ${CERTSERIAL} signingkey_password = password _EOF_ cat <<_EOF_ > "${workdir}/swtpm-localca.options" --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 2 --platform-manufacturer Fedora --platform-version 2.1 --platform-model QEMU _EOF_ # the following contains the test parameters and # expected key usage for testparams in \ "--allow-signing|Digital signature" \ "--allow-signing --decryption|Digital signature,Key encipherment" \ "--decryption|Key encipherment" \ "|Key encipherment"; do params=$(echo ${testparams} | cut -d"|" -f1) usage=$(echo ${testparams} | cut -d"|" -f2) ${SWTPM_LOCALCA} \ --type ek \ --ek "${ek}" \ --dir "${workdir}" \ --vmid test \ --tpm2 \ --configfile "${workdir}/swtpm-localca.conf" \ --optsfile "${workdir}/swtpm-localca.options" \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \ ${params} if [ $? -ne 0 ]; then echo "Error: Test with parameters '$params' failed." exit 1 fi # Signing key should always be password protected if [ -z "$(grep "ENCRYPTED PRIVATE KEY" "${SIGNINGKEY}")" ]; then echo "Error: Signing key is not password protected." exit 1 fi # For the root CA's key we flip the password protection if [ -n "${SWTPM_ROOTCA_PASSWORD}" ] ;then if [ -z "$(grep "ENCRYPTED PRIVATE KEY" "${workdir}/swtpm-localca-rootca-privkey.pem")" ]; then echo "Error: Root CA's private key is not password protected." exit 1 fi unset SWTPM_ROOTCA_PASSWORD else if [ -n "$(grep "ENCRYPTED PRIVATE KEY" "${workdir}/swtpm-localca-rootca-privkey.pem")" ]; then echo "Error: Root CA's private key is password protected but should not be." exit 1 fi export SWTPM_ROOTCA_PASSWORD=xyz fi if [ ! -r "${workdir}/ek.cert" ]; then echo "Error: ${workdir}/ek.cert was not created." exit 1 fi OIFS="$IFS" IFS="," for u in $usage; do echo $u if [ -z "$(${CERTTOOL} -i \ --inder --infile "${workdir}/ek.cert" | \ grep "Key Usage" -A2 | \ grep "$u")" ]; then echo "Error: Could not find key usage $u in key created " \ "with $params." else echo "Found '$u'" fi done IFS="$OIFS" ${CERTTOOL} \ -i \ --inder --infile "${workdir}/ek.cert" \ --outfile "${workdir}/ek.pem" ${CERTTOOL} \ --verify \ --load-ca-certificate "${ISSUERCERT}" \ --infile "${workdir}/ek.pem" if [ $? -ne 0 ]; then echo "Error: Could not verify certificate chain." exit 1 fi # Delete all keys to have CA re-created rm -rf "${workdir}"/*.pem done echo "Test 1: OK" echo #A few tests with odd vm Ids for vmid in \ 's p a c e|s p a c e' \ '$(ls)>foo|$(ls)\>foo' \ '`ls`&; #12|`ls`&\; #12' \ 'foo>&1<&2;$(ls)|foo\>&1\<&2\;$(ls)' \ "'*|'*" \ '"*|\"*' \ ':$$|:$$' \ '${t}[]|${t}[]'; do in=$(echo "$vmid" | cut -d"|" -f1) exp=$(echo "$vmid" | cut -d"|" -f2) ${SWTPM_LOCALCA} \ --type ek \ --ek "${ek}" \ --dir "${workdir}" \ --vmid "$in" \ --tpm2 \ --configfile "${workdir}/swtpm-localca.conf" \ --optsfile "${workdir}/swtpm-localca.options" \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \ ${params} &>/dev/null if [ $? -ne 0 ]; then echo "Error: Test with parameters '$params' failed." exit 1 fi if [ ! -r "${workdir}/ek.cert" ]; then echo "Error: ${workdir}/ek.cert was not created." exit 1 fi ac=$(${CERTTOOL} -i --inder --infile "${workdir}/ek.cert" | \ sed -n "s/.*Subject: CN=\(.*\)$/\1/p") if [ "$ac" != "$exp" ]; then echo "Error: unexpected subject string" echo "actual : $ac" echo "expected : $exp" else echo "Pass: $ac" fi done echo "Test 2: OK" exit 0 swtpm-0.6.3/tests/test_tpm2_samples_swtpm_localca_pkcs11000077500000000000000000000121331421141172300235150ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x TOPBUILD=${abs_top_builddir:-$(dirname "$0")/..} TOPSRC=${abs_top_srcdir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM_LOCALCA=${TOPBUILD}/samples/swtpm-localca workdir=$(mktemp -d) if [ $? -ne 0 ]; then exit 1 fi # Have softhsm_setup use 'workdir'. export SOFTHSM_SETUP_CONFIGDIR="${workdir}" # Since we will be using the pkcs11 module as well via certtool # we have to set the environment variable to point to its config file. # This has to be the same as for swtpm_setup sets it. export SOFTHSM2_CONF="${workdir}"/softhsm2.conf ek="80" # 2048 bit key must have highest bit set for ((i = 1; i < 256; i++)); do ek="${ek}$(printf "%02x" $i)" done SIGNINGKEY=${workdir}/signingkey.pem ISSUERCERT=${workdir}/issuercert.pem CERTSERIAL=${workdir}/certserial PATH=${TOPBUILD}/src/swtpm_cert:$PATH source ${TESTDIR}/common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf ${workdir} ${TESTDIR}/softhsm_setup teardown } unset GNUTLS_PIN export PIN="abcdef" # Generate the PKCS11 token and key; it uses env. variable 'PIN' msg=$(${TESTDIR}/softhsm_setup setup 2>&1) if [ $? -ne 0 ]; then echo -e "Could not setup softhsm:\n${msg}" echo "softhsm needs to be v2.3.0 or greater and pkcs11 correctly configured" exit 77 fi pkcs11uri=$(echo ${msg} | sed -n 's|^keyuri: \(.*\)|\1|p') # Now we need to create the root CA ... template=${workdir}/template cakey=${workdir}/swtpm-localca-rootca-privkey.pem cacert=${workdir}/swtpm-localca-rootca-cert.pem # first the private key msg=$(${CERTTOOL} \ --generate-privkey \ --outfile ${cakey} \ ${passparam} \ 2>&1) if [ $? -ne 0 ]; then echo "Could not create root-CA key ${cakey}." echo "${msg}" exit 1 fi chmod 640 ${cakey} # now the self-signed certificate cat <<_EOF_ >${template} cn=swtpm-localca-rootca ca cert_signing_key expiration_days = 3650 _EOF_ msg=$(${CERTTOOL} \ --generate-self-signed \ --template ${template} \ --outfile ${cacert} \ --load-privkey ${cakey} \ 2>&1) if [ $? -ne 0 ]; then echo "Could not create root CA." echo "${msg}" exit 1 fi # And now create the intermediate CA with the pkcs11 URI key pubkey=${workdir}/swtpm-localca-interm-pubkey.pem msg=$(GNUTLS_PIN=${PIN} ${CERTTOOL} \ --load-privkey ${pkcs11uri} \ --pubkey-info \ --outfile ${pubkey}) if [ $? -ne 0 ]; then echo "Could not get public key for pkcs11 uri key ($pkcs11uri}." echo "${msg}" exit 1 fi cat <<_EOF_ > ${template} cn=swtpm-localca ca cert_signing_key expiration_days = 3650 _EOF_ msg=$(GNUTLS_PIN=${PIN} ${CERTTOOL} \ --generate-certificate \ --template ${template} \ --outfile ${ISSUERCERT} \ --load-ca-privkey ${cakey} \ --load-ca-certificate ${cacert} \ --load-privkey ${pkcs11uri} \ --load-pubkey ${pubkey} \ 2>&1) if [ $? -ne 0 ]; then echo "Could not create intermediate CA" echo "${msg}" exit 1 fi echo -n 1 > ${CERTSERIAL} # Now we can create the config files cat <<_EOF_ > ${workdir}/swtpm-localca.conf statedir = ${workdir} signingkey = $(echo ${pkcs11uri} | sed 's|;|\\;|g') issuercert = ${ISSUERCERT} certserial = ${CERTSERIAL} SWTPM_PKCS11_PIN = ${PIN} _EOF_ cat <<_EOF_ > ${workdir}/swtpm-localca.options --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 2 --platform-manufacturer Fedora --platform-version 2.1 --platform-model QEMU _EOF_ # the following contains the test parameters and # expected key usage for testparams in \ "--allow-signing|Digital signature" \ "--allow-signing --decryption|Digital signature,Key encipherment" \ "--decryption|Key encipherment" \ "|Key encipherment"; do params=$(echo ${testparams} | cut -d"|" -f1) usage=$(echo ${testparams} | cut -d"|" -f2) msg=$(${SWTPM_LOCALCA} \ --type ek \ --ek ${ek} \ --dir ${workdir} \ --vmid test \ --tpm2 \ --configfile ${workdir}/swtpm-localca.conf \ --optsfile ${workdir}/swtpm-localca.options \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 \ ${params} 2>&1) if [ $? -ne 0 ]; then echo "Error: Test with parameters '$params' failed." echo "${msg}" if [[ "${msg}" =~ The\ requested\ PKCS\ #11\ object\ is\ not\ available ]]; then # could be related to i386 executables on x86_64 host and # libsofthsm.so only available for x86_64... exit 77 fi exit 1 fi if [ ! -r ${workdir}/ek.cert ]; then echo "${msg}" echo "Error: ${workdir}/ek.cert was not created." exit 1 fi OIFS="$IFS" IFS="," for u in $usage; do if [ -z "$(${CERTTOOL} -i \ --inder --infile ${workdir}/ek.cert | \ grep "Key Usage" -A2 | \ grep "$u")" ]; then echo "Error: Could not find key usage $u in key created " \ "with $params." else echo "Found '$u'" fi done IFS="$OIFS" ${CERTTOOL} \ -i \ --inder --infile ${workdir}/ek.cert \ --outfile ${workdir}/ek.pem GNUTLS_PIN=${PIN} ${CERTTOOL} \ --verify \ --load-ca-certificate ${ISSUERCERT} \ --infile ${workdir}/ek.pem if [ $? -ne 0 ]; then echo "Error: Could not verify certificate chain." exit 1 fi done exit 0 swtpm-0.6.3/tests/test_tpm2_save_load_encrypted_state000077500000000000000000000016431421141172300231750ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65528 export SWTPM_CTRL_PORT=65529 bash _test_tpm2_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65528 bash _test_tpm2_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_save_load_encrypted_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_save_load_state000077500000000000000000000015611421141172300211170ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65452 export SWTPM_CTRL_PORT=65453 bash _test_tpm2_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65452 bash _test_tpm2_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_save_load_state ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_save_load_state_2000077500000000000000000000204201421141172300213330ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x if [ ${SWTPM_TEST_IBMTSS2:-0} -eq 0 ]; then echo "SWTPM_TEST_IBMTSS2 must be set to run this test." exit 77 fi type -p nvdefinespace startup &>/dev/null if [ $? -ne 0 ]; then PREFIX=tss type -p ${PREFIX}nvdefinespace ${PREFIX}startup fi if [ $? -ne 0 ]; then echo "Could not find TPM2 tools (e.g., (tss)startup, (tss)nvdefinespace) in PATH." exit 77 fi TOOLSPATH=$(dirname $(type -P ${PREFIX}startup)) ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} SWTPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl TPMDIR=`mktemp -d` PID_FILE=$TPMDIR/${SWTPM}.pid SOCK_PATH=$TPMDIR/sock CMD_PATH=$TPMDIR/cmd RESP_PATH=$TPMDIR/resp LOGFILE=$TPMDIR/logfile TMPFILE=$TPMDIR/tmpfile BINFILE=$TPMDIR/binfile SIGFILE=$TPMDIR/sigfile source ${TESTDIR}/test_common source ${TESTDIR}/common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR # remove files from tss tools rm -f h01*.bin nvp*.bin if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } # Fill up the NVRAM space with 2048 bit signing keys and then an NVRAM area that # fills it up to the last byte. We want to make sure that the OBJECTs that the # RSA keys are creating in NVRAM can be loaded into the NVRAM again when the size # of the OBJECT increases when for example the size of the RSA keys increases. # This may force us to increase the NVRAM memory space in libtpms then. function fillup_nvram() { local create="$1" local check="$2" local i sz if [ $create -eq 1 ]; then # Fill up the NVRAM space with RSA 2048 keys; # exactly 65 have to fit ${TOOLSPATH}/${PREFIX}createprimary -hi o -si > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" exit 1 fi for ((i = 0x81000000; i < 0x81000100; i++)); do ${TOOLSPATH}/${PREFIX}evictcontrol \ -hi o \ -ho 80000000 \ -hp $(printf "%x" $i) &>$TMPFILE || break done ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 81000000 -pc 80 > $TMPFILE # We need know we need to see '65 Handles' for state created with # libtpms-0.6.0 and 128kb NVRAM size grep -i "65 Handles" $TMPFILE if [ $? -ne 0 ]; then echo "Error: Did not find '65 Handles' keyword in output" cat $TMPFILE exit 1 fi # Fill up the rest of the NVRAM with a single NVRAM index whose size # we now have to find; # for reference: libtpms v0.6.0 allowed 236 bytes for ((sz = 0; ; sz++)); do ${TOOLSPATH}/${PREFIX}nvdefinespace \ -hi o \ -ha 01000000 \ -sz ${sz} > ${TMPFILE} || break # this worked, so lets remove it and try the next size #echo "NVRAM space of size $sz could be created" ${TOOLSPATH}/${PREFIX}nvundefinespace \ -hi o \ -ha 01000000 > ${TMPFILE} done if [ $sz -gt 0 ]; then sz=$((sz - 1)) echo "Creating final space of size ${sz}" ${TOOLSPATH}/${PREFIX}nvdefinespace \ -hi o \ -ha 01000000 \ -sz ${sz} > ${TMPFILE} if [ $? -ne 0 ]; then echo "Error: Could not create final NVRAM space." cat ${TMPFILE} exit 1 fi fi if [ $sz -eq 0 ]; then echo "Error: NVRAM space could not be created at all; not enough space!" exit 1 elif [ $sz -lt 236 ]; then echo "Error: Insufficient NVRAM memory. Needed to create an NVRAM index with size 236 bytes." exit 1 elif [ $sz -gt 236 ]; then echo "Error: The NVRAM index is too large. Only needed 236 bytes but got $sz bytes." exit 1 else echo "The NVRAM index is exactly of the right size (236 bytes)." fi echo -n "123" > $BINFILE ${TOOLSPATH}/${PREFIX}sign \ -hk 81000000 \ -if ${BINFILE} \ -os ${SIGFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not create signature." cat $TMPFILE exit 1 fi fi if [ $check -eq 1 ]; then ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 81000000 -pc 80 > $TMPFILE # We need know we need to see '65 Handles' for state created with # libtpms-0.6.0 and 128kb NVRAM size grep -i "65 Handles" $TMPFILE if [ $? -ne 0 ]; then echo "Error: Did not find '65 Handles' keyword in output" cat $TMPFILE exit 1 fi printf "Verifying signature with all the persisted keys\n" echo -n "123" > $BINFILE for ((i = 0x81000000; i < 0x81000040; i++)); do ${TOOLSPATH}/${PREFIX}verifysignature \ -hk $(printf "%x" $i) \ -is ${SIGFILE} \ -if ${BINFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Verifying signature failed for handle $(printf "%x" $i)." exit 1 fi done fi } export TPM_SERVER_TYPE=raw export TPM_SERVER_NAME=127.0.0.1 export TPM_INTERFACE_TYPE=socsim export TPM_COMMAND_PORT=65446 export TPM_DATA_DIR=$TPMDIR export TPM_SESSION_ENCKEY="807e2bfe898ddaed8fa6310e716a24dc" # for sessions $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (1) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." exit 1 fi fillup_nvram 1 1 # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: swtpm did not shut down" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" # Store this state for later usage; use a really old version of libtpms: 0.6.0 #cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state5; #cp $SIGFILE ${TESTDIR}/data/tpm2state5/signature.bin ################################################################# # Run TPM2 with the created state and verify it's the same $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (2) Socket TPM did not write pidfile." exit 1 fi echo "TPM re-started" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" cat $LOGFILE exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi fillup_nvram 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" ################################################################# # Run TPM2 with previously saved state and verify it's the same rm -f $TPMDIR/* cp -f ${TESTDIR}/data/tpm2state5/tpm2-00.permall $TPMDIR/tpm2-00.permall cp ${TESTDIR}/data/tpm2state5/signature.bin $SIGFILE $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi fillup_nvram 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 1 OK" swtpm-0.6.3/tests/test_tpm2_save_load_state_3000077500000000000000000001020371421141172300213410ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x if [ ${SWTPM_TEST_IBMTSS2:-0} -eq 0 ]; then echo "SWTPM_TEST_IBMTSS2 must be set to run this test." exit 77 fi type -p nvdefinespace startup &>/dev/null if [ $? -ne 0 ]; then PREFIX=tss type -p ${PREFIX}nvdefinespace ${PREFIX}startup fi if [ $? -ne 0 ]; then echo "Could not find TPM2 tools (e.g., (tss)startup, (tss)nvdefinespace) in PATH." exit 77 fi TOOLSPATH=$(dirname $(type -P ${PREFIX}startup)) ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} SWTPM_IOCTL=$ROOT/src/swtpm_ioctl/swtpm_ioctl TPMDIR=`mktemp -d` PID_FILE=$TPMDIR/${SWTPM}.pid SOCK_PATH=$TPMDIR/sock CMD_PATH=$TPMDIR/cmd RESP_PATH=$TPMDIR/resp LOGFILE=$TPMDIR/logfile VOLATILESTATE=$TPMDIR/volatile TMPFILE=$TPMDIR/tmpfile BINFILE=$TPMDIR/binfile SIGFILE=$TPMDIR/sigfile SIGFILE2=$TPMDIR/sigfile2 TMP2FILE=$TPMDIR/tmpfile2 PRIVKEY=$TPMDIR/privkey.pem PUBKEY=$TPMDIR/pubkey.pem PUBKEYCONTEXT=$TPMDIR/pubkey.context HKEYPRIV=${TESTDIR}/data/tpm2state3/hkey.priv HKEYPUB=${TESTDIR}/data/tpm2state3/hkey.pub source ${TESTDIR}/test_common source ${TESTDIR}/common trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf $TPMDIR # remove files from tss tools rm -f h01*.bin nvp*.bin if [ -n "$PID" ]; then kill_quiet -SIGTERM $PID 2>/dev/null fi } function test_nvram_state() { local create="$1" local check="$2" local i res rc act exp ody if [ $create -eq 1 ]; then # the 1st and 2nd spaces are 'orderly' and will be cleared by reset ody="+at ody" for ((i=0; i < 10; i++)); do printf "Creating NVRAM location 01%06x\n" $i # the '+at wd' allows us to only write once ${TOOLSPATH}/${PREFIX}nvdefinespace \ -ha $(printf "01%06x" $i) \ -sz $((100 + i * 10)) \ -pwdn nnn \ +at wst \ +at wd \ $ody \ -hi o >/dev/null if [ $? -ne 0 ]; then echo "Error: nvdefinespace failed for i = $i." exit 1 fi if [ $i -eq 1 ]; then ody="" fi ${TOOLSPATH}/${PREFIX}nvwrite \ -ha $(printf "01%06x" $i) \ -ic "Hello TPM2" \ -pwdn nnn if [ $? -ne 0 ]; then echo "Error: nwrite failed for i = $i." exit 1 fi ${TOOLSPATH}/${PREFIX}nvwritelock \ -ha $(printf "01%06x" $i) \ -pwdn nnn if [ $? -ne 0 ]; then echo "Error: nwritelock failed for i = $i." exit 1 fi done # Create a counter space echo "Creating NVRAM location 01000010 for counter" ${TOOLSPATH}/${PREFIX}nvdefinespace \ -hi o \ -ha 01000010 \ -pwdn nnn \ -ty c >/dev/null if [ $? -ne 0 ]; then echo "Error: nvdefinespace for counter failed." exit 1 fi echo "Incrementing the counter at location 01000010" ${TOOLSPATH}/${PREFIX}nvincrement \ -ha 01000010 \ -pwdn nnn >/dev/null if [ $? -ne 0 ]; then echo "Error: nvincrement failed." exit 1 fi fi if [ $check -eq 1 ]; then local last=0 if [ $create -eq 0 ]; then last=2 fi # The orderly indices must not be readable UNLESS they were just # created. In the latter case we skip this first loop here. for ((i=0; i < last; i++)); do printf "Checking orderly NVRAM location 01%06x after reset\n" $i ${TOOLSPATH}/${PREFIX}nvread \ -ha $(printf "01%06x" $i) \ -pwdn nnn \ -sz 10 > $TMPFILE if [ $? -eq 0 ]; then echo "Error: nvread succeeded for orderly NVRAM index; i = $i" cat $TMPFILE exit 1 fi done # test the non-orderly indices OR orderly we just created above for ((i=last; i < 10; i++)); do printf "Checking NVRAM location 01%06x\n" $i ${TOOLSPATH}/${PREFIX}nvread \ -ha $(printf "01%06x" $i) \ -pwdn nnn \ -sz 10 > $TMPFILE if [ $? -ne 0 ]; then echo "Error: nvread failed for i = $i" cat $TMPFILE exit 1 fi # we want one line with xdigits and spaces res=$(cat $TMPFILE | \ grep -E "^[ [:xdigit:]]+$" | wc -l) if [ $res -ne 1 ]; then echo "Error: nvread did not show expected results" cat $TMPFILE fi ${TOOLSPATH}/${PREFIX}nvwrite \ -ha $(printf "01%06x" $i) \ -ic "Hello TPM2" \ -pwdn nnn > $TMPFILE rc=$? if [ $rc -eq 0 ]; then echo "Error: nwrite succeeded for i = $i." exit 1 fi done # Read the counter echo "Checking counter value at location 01000010" ${TOOLSPATH}/${PREFIX}nvread \ -ha 01000010 \ -pwdn nnn \ -sz 8 \ -of $BINFILE > $TMPFILE if [ $? -ne 0 ]; then echo "Error: nvread of counter failed." cat $TMPFILE exit 1 fi exp=' 00 00 00 00 00 00 00 01' act="$(od -t x1 -A n < $BINFILE)" if [ "$act" != "$exp" ]; then echo "Error: Counter has unexpected value." echo " expected: $exp" echo " actual : $act" fi fi } function test_primary() { local create="$1" local check="$2" # whether we are using previous stored stated that had a different # key and we have to use the old signature local previousstate="$3" local i res rc if [ $create -eq 1 ]; then # Create a permanent primary key that we expecte # to again see after the TPM has been restarted ${TOOLSPATH}/${PREFIX}createprimary -hi o -si > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" exit 1 fi ${TOOLSPATH}/${PREFIX}evictcontrol -ho 80000000 -hp 81000000 -hi o if [ $? -ne 0 ]; then echo "Error: evictcontrol did not work" exit 1 fi ${TOOLSPATH}/${PREFIX}flushcontext -ha 80000000 echo -n "123" > $BINFILE ${TOOLSPATH}/${PREFIX}sign -hk 81000000 -if ${BINFILE} -os ${SIGFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not create signature." cat $TMPFILE exit 1 fi fi if [ $check -eq 1 ]; then printf "Checking availability of key with perm. handle 0x81000000\n" ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 0x81000000 >$TMPFILE if [ -z "$(grep 81000000 $TMPFILE)" ]; then echo "Could not find key with permanent handle 0x81000000" exit 1 fi printf "Verifying signature with this key\n" echo -n "123" > $BINFILE if [ $previousstate -eq 0 ]; then ${TOOLSPATH}/${PREFIX}verifysignature -hk 81000000 \ -is ${SIGFILE} \ -if ${BINFILE} > $TMPFILE else ${TOOLSPATH}/${PREFIX}verifysignature -hk 81000000 \ -is ${TESTDIR}/data/tpm2state3/signature.bin \ -if ${BINFILE} > $TMPFILE fi if [ $? -ne 0 ]; then echo "Verifying signature failed." exit 1 fi fi } # Allocate a SHA256 PCR bank # This will prevent shutdown -s (with state) function test_pcr_allocation() { local create="$1" local check="$2" local i res rc ha if [ -z "$($TOOLSPATH/${PREFIX}pcrallocate | grep sha512)" ]; then echo " Skipping PCR Allocate test since it does not support sha512" return 0 fi if [ $create -eq 1 ]; then echo "Allocating SHA256 PCR bank" ${TOOLSPATH}/${PREFIX}pcrallocate -sha512 +sha256 for ((ha = 0; ha < 24; ha++)); do ${TOOLSPATH}/${PREFIX}pcrread -ha ${ha} -halg sha512 > $TMPFILE if [ -z "$(grep "^count 1.*$" $TMPFILE)" ]; then echo "Error: PCR ${ha} in SHA512 bank should be available for read before reboot" cat $TMPFILE exit 1 fi ${TOOLSPATH}/${PREFIX}pcrread -ha ${ha} -halg sha256 > $TMPFILE if [ -z "$(grep "^count 1.*$" $TMPFILE)" ]; then echo "Error: PCR ${ha} in SHA256 bank should be available for read before reboot" cat $TMPFILE exit 1 fi done fi if [ $check -eq 1 ]; then echo "Checking the PCR Allocation" for ((ha = 0; ha < 24; ha++)); do ${TOOLSPATH}/${PREFIX}pcrread -ha ${ha} -halg sha512 > $TMPFILE if [ -z "$(grep "^count 0.*$" $TMPFILE)" ]; then echo "Error: PCR ${ha} in SHA512 bank should be unavailable for read after reboot" cat $TMPFILE exit 1 fi ${TOOLSPATH}/${PREFIX}pcrread -ha ${ha} -halg sha256 > $TMPFILE if [ -z "$(grep "^count 1.*$" $TMPFILE)" ]; then echo "Error: PCR ${ha} in SHA256 bank should be available for read after reboot" exit 1 fi done fi } function test_hierarchy() { local create="$1" local check="$2" local hi pwdn pwda if [ $create -eq 1 ]; then echo "Setting hierarchy passwords" # Change the hierarchy password; the 'p' hierarchy has # no effect on permanent RAM, so we won't test that for hi in "l" "e" "o"; do pwdn="${hi}${hi}${hi}" ${TOOLSPATH}/${PREFIX}hierarchychangeauth \ -hi ${hi} \ -pwdn ${pwdn} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: hierarchychangeauth failed to set password." cat $TMPFILE exit 1 fi done fi if [ $check -eq 1 ]; then echo "Checking previously set hierarchy passwords" for hi in "l" "e" "o"; do pwda="${hi}${hi}${hi}" pwdn="new-${pwda}" ${TOOLSPATH}/${PREFIX}hierarchychangeauth \ -hi ${hi} \ -pwda ${pwda} \ -pwdn ${pwdn} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: hierarchychangeauth failed to change password." cat $TMPFILE exit 1 fi # change back ${TOOLSPATH}/${PREFIX}hierarchychangeauth \ -hi ${hi} \ -pwda ${pwdn} \ -pwdn ${pwda} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: hierarchychangeauth failed to change back password." cat $TMPFILE exit 1 fi done fi } function test_hash_context() { local create="$1" local check="$2" local res tmpfile if [ $create -eq 1 ]; then echo -n "123" > ${TMP2FILE} echo "Starting a sha1 sequence" res="$(${TOOLSPATH}/${PREFIX}hashsequencestart -halg sha1)" if [ $? -ne 0 ]; then echo "Error: Could not start hash sequence." exit 1 fi SHA1_SEQUENCE_HANDLE="$(echo $res | cut -d " " -f3)" echo "sha1 sequence handle: $SHA1_SEQUENCE_HANDLE" ${TOOLSPATH}/${PREFIX}sequenceupdate \ -hs ${SHA1_SEQUENCE_HANDLE} \ -if ${TMP2FILE} if [ $? -ne 0 ]; then echo "Error: Could not updated the sha1 sequence." exit 1 fi echo "Updated sha1 sequence." echo "Starting a sha256 sequence" res="$(${TOOLSPATH}/${PREFIX}hashsequencestart -halg sha256)" if [ $? -ne 0 ]; then echo "Error: Could not start sha256 sequence." exit 1 fi SHA256_SEQUENCE_HANDLE="$(echo $res | cut -d " " -f3)" echo "sha256 sequence handle: $SHA256_SEQUENCE_HANDLE" ${TOOLSPATH}/${PREFIX}sequenceupdate \ -hs ${SHA256_SEQUENCE_HANDLE} \ -if ${TMP2FILE} if [ $? -ne 0 ]; then echo "Error: Could not updated the hash sequence." exit 1 fi echo "Updated sha256 sequence." echo "Starting a sha384 sequence" res="$(${TOOLSPATH}/${PREFIX}hashsequencestart -halg sha384)" if [ $? -ne 0 ]; then echo "Error: Could not start sha384 sequence." exit 1 fi SHA384_SEQUENCE_HANDLE="$(echo $res | cut -d " " -f3)" echo "sha384 sequence handle: $SHA384_SEQUENCE_HANDLE" ${TOOLSPATH}/${PREFIX}sequenceupdate \ -hs ${SHA384_SEQUENCE_HANDLE} \ -if ${TMP2FILE} if [ $? -ne 0 ]; then echo "Error: Could not updated the hash sequence." exit 1 fi echo "Updated sha384 sequence." fi if [ $check -eq 1 ]; then echo -n "456" > ${TMP2FILE} echo "Completing previously started sha1 sequence" touch $TPMDIR/h${SHA1_SEQUENCE_HANDLE}.bin res=$(${TOOLSPATH}/${PREFIX}sequencecomplete \ -hs ${SHA1_SEQUENCE_HANDLE} \ -if ${TMP2FILE} -v | tail -n 4 | grep " 7c 4a 8d ") if [ -z "$res" ]; then echo "Error: Did not get expected result from completing sha1 sequence." exit 1 fi echo "Completing previously started sha256 sequence" touch $TPMDIR/h${SHA256_SEQUENCE_HANDLE}.bin res=$(${TOOLSPATH}/${PREFIX}sequencecomplete \ -hs ${SHA256_SEQUENCE_HANDLE} \ -if ${TMP2FILE} -v | tail -n 4 | grep " 8d 96 9e ") if [ -z "$res" ]; then echo "Error: Did not get expected result from completing sha256 sequence." exit 1 fi echo "Completing previously started sha384 sequence" touch $TPMDIR/h${SHA384_SEQUENCE_HANDLE}.bin res=$(${TOOLSPATH}/${PREFIX}sequencecomplete \ -hs ${SHA384_SEQUENCE_HANDLE} \ -if ${TMP2FILE} -v | tail -n 4 | grep " 0a 98 9e ") if [ -z "$res" ]; then echo "Error: Did not get expected result from completing sha384 sequence." exit 1 fi fi } function test_session() { local create="$1" local check="$2" # whether we are using previous stored stated that had a different # key and we have to use the old signature local previousstate="$3" local i res rc if [ $create -eq 1 ]; then # Create a permanent primary key that we expecte # to again see after the TPM has been restarted ${TOOLSPATH}/${PREFIX}createprimary -hi o -st > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary for creating storage key failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" cat $TMPFILE exit 1 fi ${TOOLSPATH}/${PREFIX}evictcontrol -ho 80000000 -hp 81000000 -hi o if [ $? -ne 0 ]; then echo "Error: evictcontrol did not work" exit 1 fi ${TOOLSPATH}/${PREFIX}flushcontext -ha 80000000 ${TOOLSPATH}/${PREFIX}startauthsession -se h -bi 81000000 > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not start an auth session." cat $TMPFILE exit 1 fi AUTHSESSION_HANDLE=$(cat $TMPFILE | sed 's/Handle//') if [ -z "${AUTHSESSION_HANDLE}" ]; then echo "Error: Could not get auth session handle." exit 1 fi fi if [ $check -eq 1 ]; then echo "Using auth session ${AUTHSESSION_HANDLE} to create a key." ${TOOLSPATH}/${PREFIX}create \ -hp 81000000 \ -st \ -se0 ${AUTHSESSION_HANDLE} 1 if [ $? -ne 0 ]; then echo "Error: Could not create key using authsession" exit 1 fi echo "Successfully created key" fi } function test_hmac_context() { local create="$1" local check="$2" # whether we are using previous stored stated that had a different # key and we have to use the old signature local previousstate="$3" local i res rc if [ $create -eq 1 ]; then ${TOOLSPATH}/${PREFIX}createprimary -hi o -st > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" exit 1 fi ${TOOLSPATH}/${PREFIX}create -hp 80000000 -kh \ -opr ${HKEYPRIV} -opu ${HKEYPUB} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: could not create key for HMAC" exit 1 fi ${TOOLSPATH}/${PREFIX}load -hp 80000000 \ -ipr ${HKEYPRIV} -ipu ${HKEYPUB} -v > $TMPFILE if [ $? -ne 0 ]; then echo "Error: could not load key for HMAC" cat $TMPFILE exit 1 fi if [ -z "$(grep 80000001 $TMPFILE)" ]; then echo "Error: load did not result in expected handle 80000001" exit 1 fi ${TOOLSPATH}/${PREFIX}hmacstart -hk 80000001 > $TMPFILE if [ $? -ne 0 ]; then echo "Error: could not start HMAC sequence" exit 1 fi if [ -z "$(grep 80000002 $TMPFILE)" ]; then echo "Error: load did not result in expected handle 80000002" exit 1 fi echo -n "123" > ${TMP2FILE} ${TOOLSPATH}/${PREFIX}sequenceupdate \ -hs 80000002 \ -if ${TMP2FILE} if [ $? -ne 0 ]; then echo "Error: Could not updated the HMAC sequence." exit 1 fi echo "Updated HMAC sequence." fi if [ $check -eq 1 ]; then echo -n "456" > ${TMP2FILE} echo "Completing previously started HMAC sequence" touch $TPMDIR/h80000002.bin ${TOOLSPATH}/${PREFIX}sequencecomplete \ -hs 80000002 \ -if ${TMP2FILE} -v | tail -n 4 > ${TMPFILE} if [ -z "$(grep " 6e 40 33 1a " ${TMPFILE})" ]; then echo "Error: Did not get expected result from completing HMAC sequence." cat $TMPFILE exit 1 fi fi } function test_primary_volatile_load() { local create="$1" local check="$2" # whether we are using previous stored stated that had a different # key and we have to use the old signature local previousstate="$3" local i res rc if [ $create -eq 1 ]; then # Create a permanent primary key that we expecte # to again see after the TPM has been restarted ${TOOLSPATH}/${PREFIX}createprimary -hi o -si > $TMPFILE if [ $? -ne 0 ]; then echo "Error: createprimary failed." exit 1 fi if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Error: createprimary did not result in expected handle 80000000" exit 1 fi echo -n "123" > $BINFILE ${TOOLSPATH}/${PREFIX}sign -hk 80000000 -if ${BINFILE} -os ${SIGFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not create signature." cat $TMPFILE exit 1 fi printf "Verifying signature with this key (create phase)\n" ${TOOLSPATH}/${PREFIX}verifysignature -hk 80000000 \ -is ${SIGFILE} \ -if ${BINFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Verifying signature failed." exit 1 fi fi if [ $check -eq 1 ]; then local sigfile=${SIGFILE} hash1 hash2 if [ $previousstate -ne 0 ]; then sigfile=${TESTDIR}/data/tpm2state3d/signature2.bin fi printf "Checking availability of key with handle 0x80000000\n" ${TOOLSPATH}/${PREFIX}getcapability -cap 1 -pr 0x80000000 >$TMPFILE if [ -z "$(grep 80000000 $TMPFILE)" ]; then echo "Could not find key with handle 0x80000000" exit 1 fi printf "Verifying signature with this key (check phase)\n" echo -n "123" > $BINFILE ${TOOLSPATH}/${PREFIX}verifysignature -hk 80000000 \ -is ${sigfile} \ -if ${BINFILE} > $TMPFILE if [ $? -ne 0 ]; then echo "Verifying signature failed." exit 1 fi if [ $previousstate -eq 0 ]; then ${TOOLSPATH}/${PREFIX}sign -hk 80000000 -if ${BINFILE} -os ${SIGFILE2} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: Could not create signature." cat $TMPFILE exit 1 fi hash1=$(get_sha1_file ${SIGFILE}) hash2=$(get_sha1_file ${SIGFILE2}) if [ "${hash1}" != "${hash2}" ]; then echo "Error: hashes of signatures are different. Loaded key may be different." exit 1 fi fi fi } # libtpms issue #195: Create an external key and load it into the TPM 2 # and do a context save/load cycle function test_external_key() { local create="$1" local check="$2" if [ $create -eq 1 ]; then ${CERTTOOL} --generate-privkey --bits 2048 --outfile ${PRIVKEY} &>/dev/null ${CERTTOOL} --pubkey-info --load-privkey ${PRIVKEY} > ${PUBKEY} $TOOLSPATH/${PREFIX}loadexternal -hi o -ipem ${PUBKEY} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: loadexternal failed." exit 1 fi if [ -z "$(grep 80000001 $TMPFILE)" ]; then echo "Error: loadexternal did not result in expected handle 80000001" exit 1 fi fi if [ $check -eq 1 ]; then $TOOLSPATH/${PREFIX}contextsave -ha 80000001 -of ${PUBKEYCONTEXT} if [ $? -ne 0 ]; then echo "Error: contextsave on loaded public key failed." exit 1 fi $TOOLSPATH/${PREFIX}flushcontext -ha 80000001 $TOOLSPATH/${PREFIX}contextload -if ${PUBKEYCONTEXT} > $TMPFILE if [ $? -ne 0 ]; then echo "Error: contextload on context of public key failed." exit 1 fi if [ -z "$(grep 80000001 $TMPFILE)" ]; then echo "Error: contextload did not result in expected handle 80000001" exit 1 fi fi } export TPM_SERVER_TYPE=raw export TPM_SERVER_NAME=127.0.0.1 export TPM_INTERFACE_TYPE=socsim export TPM_COMMAND_PORT=65533 export TPM_DATA_DIR=$TPMDIR export TPM_SESSION_ENCKEY="807e2bfe898ddaed8fa6310e716a24dc" # for sessions $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (1) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." exit 1 fi test_nvram_state 1 1 test_primary 1 1 0 test_pcr_allocation 1 0 # can only check after reboot test_hierarchy 1 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" # Store this state for later usage # cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state3; # cp $SIGFILE ${TESTDIR}/data/tpm2state3/signature.bin ################################################################# # Run TPM2 with the created state and verify it's the same $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (2) Socket TPM did not write pidfile." exit 1 fi echo "TPM re-started" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi test_nvram_state 0 1 test_primary 0 1 0 test_pcr_allocation 0 1 test_hierarchy 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "============================" >> $LOGFILE echo "TPM was shut down" ################################################################# # Run TPM2 with previously saved state and verify it's the same rm -f $TPMDIR/* cp -f ${TESTDIR}/data/tpm2state3/tpm2-00.permall $TPMDIR/tpm2-00.permall $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi test_nvram_state 0 1 test_primary 0 1 1 test_pcr_allocation 0 1 test_hierarchy 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 1 OK" # # # Tests with volatile state # # rm -f ${TPMDIR}/* $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi test_session 1 1 test_hash_context 1 0 act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ################################################################# # Run TPM2 with the saved volatile state # create a backup for running the next test... # cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state3b/tpm2-00.permall # cp $TPMDIR/tpm2-00.volatilestate ${TESTDIR}/data/tpm2state3b/tpm2-00.volatilestate # cp $TPMDIR/h02000000.bin ${TESTDIR}/data/tpm2state3b/h02000000.bin # cp $TPMDIR/h81000000.bin ${TESTDIR}/data/tpm2state3b/h81000000.bin $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then cat $LOGFILE echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi test_hash_context 0 1 test_session 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ##################################################################### # Run TPM2 with previously saved (volatile) state and verify it's # working as well cp -f ${TESTDIR}/data/tpm2state3b/tpm2-00.permall $TPMDIR/tpm2-00.permall cp -f ${TESTDIR}/data/tpm2state3b/tpm2-00.volatilestate $TPMDIR/tpm2-00.volatilestate cp -f ${TESTDIR}/data/tpm2state3b/h02000000.bin $TPMDIR/h02000000.bin cp -f ${TESTDIR}/data/tpm2state3b/h81000000.bin $TPMDIR/h81000000.bin $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" tail -n 10 $LOGFILE exit 1 fi test_hash_context 0 1 test_session 0 1 # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 2 OK" # # # Tests with volatile state -- 2nd test # # rm -f ${TPMDIR}/* $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi # we only run this to generate the AES key which is different every time... # test_hmac_context 1 0 act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ################################################################# # Run TPM2 with the saved volatile state # create a backup for running the next test... # cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state3c/tpm2-00.permall # cp $TPMDIR/tpm2-00.volatilestate ${TESTDIR}/data/tpm2state3c/tpm2-00.volatilestate #echo $TPMDIR #ls -l $TPMDIR $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then cat $LOGFILE echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi # since the AES key is different every time, we cannot run # the HMAC function that's using it since the result would # be different every time # test_hmac_context 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ##################################################################### # Run TPM2 with previously saved (volatile) state and verify it's # working as well cp -f ${TESTDIR}/data/tpm2state3c/tpm2-00.volatilestate $TPMDIR/tpm2-00.volatilestate cp -f ${TESTDIR}/data/tpm2state3c/tpm2-00.permall $TPMDIR/tpm2-00.permall $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi test_hmac_context 0 1 # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 3 OK" # # # Tests with volatile state -- 3rd test # # rm -f ${TPMDIR}/* $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}startup -c if [ $? -ne 0 ]; then echo "Error: tpm_startup clear failed." cat $LOGFILE exit 1 fi test_primary_volatile_load 1 0 0 test_external_key 1 1 act=$($SWTPM_IOCTL --unix $SOCK_PATH -v 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_STORE_VOLATILE failed: $act" exit 1 fi ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ################################################################# # Run TPM2 with the saved volatile state # create a backup for running the next test... # cp $TPMDIR/tpm2-00.volatilestate ${TESTDIR}/data/tpm2state3d/tpm2-00.volatilestate # cp $TPMDIR/tpm2-00.permall ${TESTDIR}/data/tpm2state3d/tpm2-00.permall # cp $SIGFILE ${TESTDIR}/data/tpm2state3d/signature2.bin #echo $TPMDIR #ls -l $TPMDIR $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then cat $LOGFILE echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi test_primary_volatile_load 0 1 0 test_external_key 0 1 ${TOOLSPATH}/${PREFIX}shutdown -c if [ $? -ne 0 ]; then echo "Error: tpm_shutdown clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi ##################################################################### # Run TPM2 with previously saved (volatile) state and verify it's # working as well cp -f ${TESTDIR}/data/tpm2state3d/tpm2-00.permall $TPMDIR/tpm2-00.permall cp -f ${TESTDIR}/data/tpm2state3d/tpm2-00.volatilestate $TPMDIR/tpm2-00.volatilestate $SWTPM_EXE socket \ --server port=${TPM_COMMAND_PORT} \ --tpmstate dir=$TPMDIR \ --pid file=$PID_FILE \ --ctrl type=unixio,path=$SOCK_PATH \ --log file=$LOGFILE,level=20 \ --tpm2 \ ${SWTPM_TEST_SECCOMP_OPT} & if wait_for_file $PID_FILE 3; then echo "Error: (3) Socket TPM did not write pidfile." exit 1 fi echo "TPM started with previously generated state" PID="$(cat $PID_FILE)" # Send TPM_Init act=$($SWTPM_IOCTL --unix $SOCK_PATH -i 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_INIT failed: $act" exit 1 fi test_primary_volatile_load 0 1 1 test_external_key 0 1 # Create the orderly nv indices and have them cleared (for coverage) test_nvram_state 1 1 ${TOOLSPATH}/${PREFIX}clear -hi p if [ $? -ne 0 ]; then echo "Error: clear failed." cat $LOGFILE exit 1 fi # Send Shutdown act=$($SWTPM_IOCTL --unix $SOCK_PATH -s 2>&1) if [ $? -ne 0 ]; then echo "Error: $SWTPM_IOCTL CMD_SHUTDOWN failed: $act" exit 1 fi echo "Test 4 OK" exit 0 swtpm-0.6.3/tests/test_tpm2_save_load_state_da_timeout000077500000000000000000000016501421141172300233300ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_state_da_timeout ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_save_load_state_da_timeout ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65438 export SWTPM_CTRL_PORT=65439 bash _test_tpm2_save_load_state_da_timeout ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65438 bash _test_tpm2_save_load_state_da_timeout ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_save_load_state_da_timeout ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_savestate000077500000000000000000000015231421141172300177570ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_savestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_savestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65524 export SWTPM_CTRL_PORT=65525 bash _test_tpm2_savestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65524 bash _test_tpm2_savestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_savestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_setbuffersize000077500000000000000000000015471421141172300206460ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65448 export SWTPM_CTRL_PORT=65449 bash _test_tpm2_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65448 bash _test_tpm2_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_setbuffersize ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_swtpm_bios000077500000000000000000000015301421141172300201440ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65520 export SWTPM_CTRL_PORT=65521 bash _test_tpm2_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65520 bash _test_tpm2_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_swtpm_bios ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_swtpm_cert000077500000000000000000000101341421141172300201450ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM_CERT=${SWTPM_CERT:-${ROOT}/src/swtpm_cert/swtpm_cert} cert=$(mktemp) trap "cleanup" SIGTERM EXIT function cleanup() { rm -f ${cert} } function check_cert_size() { local cert="$1" local exp="$2" # Unfortunately different GnuTLS versions may create certs of different # sizes; deactivate this test for now return local size=$(stat -c%s ${cert} 2>/dev/null) if [ $size -ne $exp ]; then echo "Warning: Certificate file has unexpected size." echo " Expected: $exp; found: $size" fi } ${SWTPM_CERT} \ --tpm2 \ --allow-signing \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \ --days 3650 \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1224 # truncate result file echo -n > ${cert} echo "Test 1: OK" ${SWTPM_CERT} \ --tpm2 \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --modulus 'b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497' \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1302 # truncate result file echo -n > ${cert} echo "Test 2: OK" ${SWTPM_CERT} \ --tpm2 \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --pubkey ${TESTDIR}/data/pubek.pem \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1367 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 3: OK" ###################### Platform Certificate ##################### ${SWTPM_CERT} \ --tpm2 \ --type platform \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --pubkey ${TESTDIR}/data/pubek.pem \ --out-cert ${cert} \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --platform-manufacturer Fedora \ --platform-model QEMU \ --platform-version 2.1 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "${cert}" 1411 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 4: OK" swtpm-0.6.3/tests/test_tpm2_swtpm_cert_ecc000077500000000000000000000066531421141172300207720ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM_CERT=${SWTPM_CERT:-${ROOT}/src/swtpm_cert/swtpm_cert} cert=$(mktemp) trap "cleanup" SIGTERM EXIT function cleanup() { rm -f ${cert} } function check_cert_size() { local cert="$1" local exp="$2" # Unfortunately different GnuTLS versions may create certs of different # sizes; deactivate this test for now return local size=$(stat -c%s ${cert} 2>/dev/null) if [ $size -ne $exp ]; then echo "Warning: Certificate file has unexpected size." echo " Expected: $exp; found: $size" fi } ${SWTPM_CERT} \ --tpm2 \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --ecc-x 61eaf811ea582656ca2a835dd1b9cd63eb196d7ff62711d6e9b8f85e580a47ca \ --ecc-y a51efdc71fd6c791a24a75beb50526aa81b44cc598e65b2d5e116084aea4cb5b \ --days 3650 \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 2.0 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "{$cert}" 948 #certtool --certificate-info --infile ${cert} #openssl x509 -in ${cert} -text # truncate result file echo -n > ${cert} echo "Test 1: OK" ${SWTPM_CERT} \ --tpm2 \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --ecc-x 61eaf811ea582656ca2a835dd1b9cd63eb196d7ff62711d6e9b8f85e580a47ca \ --ecc-y a51efdc71fd6c791a24a75beb50526aa81b44cc598e65b2d5e116084aea4cb5b \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "{$cert}" 1025 # truncate result file echo -n > ${cert} echo "Test 2: OK" ${SWTPM_CERT} \ --tpm2 \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --out-cert ${cert} \ --pubkey ${TESTDIR}/data/ecpubek.pem \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --tpm-spec-family 2.0 --tpm-spec-revision 146 --tpm-spec-level 0 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "{$cert}" 1025 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 3: OK" ###################### Platform Certificate ##################### ${SWTPM_CERT} \ --tpm2 \ --type platform \ --signkey ${TESTDIR}/data/signkey.pem \ --issuercert ${TESTDIR}/data/issuercert.pem \ --pubkey ${TESTDIR}/data/ecpubek.pem \ --out-cert ${cert} \ --days 3650 \ --subject "OU=foo,L=NewYork,ST=NY,C=US" \ --pem \ --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 1.2 \ --platform-manufacturer Fedora \ --platform-model QEMU \ --platform-version 2.1 if [ $? -ne 0 ]; then echo "Error: ${SWTPM_CERT} returned error code." exit 1 fi #expecting size to be constant check_cert_size "{$cert}" 1070 # truncate result file #certtool --certificate-info --infile ${cert} echo -n > ${cert} echo "Test 4: OK" swtpm-0.6.3/tests/test_tpm2_swtpm_setup_create_cert000077500000000000000000000065411421141172300227170ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. TOPBUILD=${abs_top_builddir:-$(dirname "$0")/..} TOPSRC=${abs_top_srcdir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} PATH=${TOPBUILD}/src/swtpm:$PATH SWTPM_SETUP=${TOPBUILD}/src/swtpm_setup/swtpm_setup SWTPM_LOCALCA=${TOPBUILD}/samples/swtpm-localca SWTPM=${TOPBUILD}/src/swtpm/swtpm workdir=$(mktemp -d "/tmp/path with spaces.XXXXXX") SIGNINGKEY=${workdir}/signingkey.pem ISSUERCERT=${workdir}/issuercert.pem CERTSERIAL=${workdir}/certserial PATH=${TOPBUILD}/src/swtpm_bios:$PATH trap "cleanup" SIGTERM EXIT function cleanup() { rm -rf "${workdir}" } # We want swtpm_cert to use the local CA and see that the # local CA script automatically creates a signingkey and # self-signed certificate cat <<_EOF_ > "${workdir}/swtpm-localca.conf" statedir=${workdir} signingkey = ${SIGNINGKEY} issuercert = ${ISSUERCERT} certserial = ${CERTSERIAL} _EOF_ cat <<_EOF_ > "${workdir}/swtpm-localca.options" --tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 2 --platform-manufacturer "Fedora XYZ" --platform-version 2.1 --platform-model "QEMU A.B" _EOF_ export MY_SWTPM_LOCALCA="${SWTPM_LOCALCA}" cat <<_EOF_ > "${workdir}/swtpm_setup.conf" create_certs_tool=\${MY_SWTPM_LOCALCA} create_certs_tool_config=${workdir}/swtpm-localca.conf create_certs_tool_options=${workdir}/swtpm-localca.options _EOF_ # We need to adapt the PATH so the correct swtpm_cert is picked export PATH=${TOPBUILD}/src/swtpm_cert:${PATH} keysizes="2048" if [ -n "$($SWTPM_SETUP --tpm2 --print-capabilities | grep tpm2-rsa-keysize-3072 )" ]; then keysizes+=" 3072" fi for keysize in $(echo $keysizes); do echo "Testing with RSA keysize $keysize" # we need to create at least one cert: --create-ek-cert $SWTPM_SETUP \ --tpm2 \ --allow-signing \ --tpm-state "${workdir}" \ --create-ek-cert \ --create-platform-cert \ --config "${workdir}/swtpm_setup.conf" \ --logfile "${workdir}/logfile" \ --tpm "${SWTPM} socket ${SWTPM_TEST_SECCOMP_OPT}" \ --rsa-keysize ${keysize} \ --overwrite if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." echo "Logfile output:" cat "${workdir}/logfile" exit 1 fi if [ ! -r "${SIGNINGKEY}" ]; then echo "Error: Signingkey file ${SIGNINGKEY} was not created." exit 1 fi if [ ! -r "${ISSUERCERT}" ]; then echo "Error: Issuer cert file ${ISSUERCERT} was not created." exit 1 fi if [ ! -r "${CERTSERIAL}" ]; then echo "Error: Cert serial number file ${CERTSERIAL} was not created." exit 1 fi rm -rf ${SIGNINGKEY} ${ISSUERCERT} ${CERTSERIAL} done echo "Test 1: OK" # we need to create at least one cert: --create-ek-cert $SWTPM_SETUP \ --tpm2 \ --ecc \ --tpm-state "${workdir}" \ --create-ek-cert \ --config "${workdir}/swtpm_setup.conf" \ --logfile "${workdir}/logfile" \ --tpm "${SWTPM} socket ${SWTPM_TEST_SECCOMP_OPT}" \ --overwrite if [ $? -ne 0 ]; then echo "Error: Could not run $SWTPM_SETUP." echo "Logfile output:" cat "${workdir}/logfile" exit 1 fi if [ ! -r "${SIGNINGKEY}" ]; then echo "Error: Signingkey file ${SIGNINGKEY} was not created." exit 1 fi if [ ! -r "${ISSUERCERT}" ]; then echo "Error: Issuer cert file ${ISSUERCERT} was not created." exit 1 fi if [ ! -r "${CERTSERIAL}" ]; then echo "Error: Cert serial number file ${CERTSERIAL} was not created." exit 1 fi echo "Test 2: OK" exit 0 swtpm-0.6.3/tests/test_tpm2_volatilestate000077500000000000000000000015421421141172300206410ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65504 export SWTPM_CTRL_PORT=65505 bash _test_tpm2_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65504 bash _test_tpm2_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm2_vtpm_proxy000077500000000000000000000060541421141172300202130ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x if [ "$(id -u)" -ne 0 ]; then echo "Need to be root to run this test." exit 77 fi ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=$ROOT/src/swtpm/$SWTPM TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm2-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm2-00.volatilestate PID_FILE=$TPM_PATH/${SWTPM}.pid SOCK_PATH=$TPM_PATH/sock CMD_PATH=$TPM_PATH/cmd RESP_PATH=$TPM_PATH/resp LOGFILE=$TPM_PATH/logfile function cleanup() { pid=$(ps aux | grep $SWTPM | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT source ${TESTDIR}/common source ${TESTDIR}/load_vtpm_proxy rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null $SWTPM_EXE chardev \ --tpm2 \ --vtpm-proxy \ --tpmstate dir=$TPM_PATH \ --ctrl type=unixio,path=$SOCK_PATH \ --flags startup-clear \ ${SWTPM_TEST_SECCOMP_OPT} \ --pid file=$PID_FILE &>$LOGFILE & sleep 0.5 PID=$(ps aux | grep $SWTPM | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') display_processes_by_name "$SWTPM" kill_quiet -0 $PID if [ $? -ne 0 ]; then echo "Error: Chardev TPM did not start." exit 1 fi TPM_DEVICE=$(sed -n 's,.*\(/dev/tpm[0-9]\+\).*,\1,p' $LOGFILE) echo "Using ${TPM_DEVICE}." # Wait for chardev to appear for ((i = 0; i < 10; i ++)); do [ -c "${TPM_DEVICE}" ] && break sleep 0.1 done if ! [ -c "${TPM_DEVICE}" ]; then echo "Error: Chardev ${TPM_DEVICE} did not appear" exit 1 fi # Open access to the TPM exec 100<>$TPM_DEVICE if [ $? -ne 0 ]; then echo "Error: Could not open $TPM_DEVICE" exit 1 fi # Read PCR 17 # length CC count hashalg sz echo -en '\x80\x01\x00\x00\x00\x14\x00\x00\x01\x7e\x00\x00\x00\x01\x00\x0b\x03\x00\x00\x02' >&100 RES=$(od -t x1 -A n -w128 <&100) exp=' 80 01 00 00 00 3e 00 00 00 00 00 00 00 14 00 00 00 01 00 0b 03 00 00 02 00 00 00 01 00 20 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi exec 100>&- kill_quiet -0 $PID if [ $? -ne 0 ]; then echo "Error: Chardev TPM must have crashed." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 echo -en '\x00\x00\x00\x03' > $CMD_PATH socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SOCK_PATH 2>&1 | \ sed -n '/^ /p' | \ tail -n1 > $RESP_PATH res="$(cat $RESP_PATH)" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_process_gone ${PID} 1; then echo "Error: TPM should not be running anymore." exit 1 fi if [ -f $PID_FILE ]; then echo "Error: TPM should have removed the PID file." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_tpm2_wrongorder000077500000000000000000000015301421141172300201460ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm2_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm2_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65512 export SWTPM_CTRL_PORT=65513 bash _test_tpm2_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65512 bash _test_tpm2_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm2_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_tpm_probe000077500000000000000000000014721421141172300170100ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_tpm_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_tpm_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65526 export SWTPM_CTRL_PORT=65527 bash _test_tpm_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65526 bash _test_tpm_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_tpm_probe ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_volatilestate000077500000000000000000000015161421141172300177000ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65420 export SWTPM_CTRL_PORT=65421 bash _test_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65420 bash _test_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_volatilestate ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0 swtpm-0.6.3/tests/test_vtpm_proxy000077500000000000000000000062701421141172300172510ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. #set -x if [ "$(id -u)" -ne 0 ]; then echo "Need to be root to run this test." exit 77 fi ROOT=${abs_top_builddir:-$(dirname "$0")/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} SWTPM=swtpm SWTPM_EXE=${SWTPM_EXE:-$ROOT/src/swtpm/$SWTPM} TPM_PATH=$(mktemp -d) STATE_FILE=$TPM_PATH/tpm-00.permall VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate PID_FILE=$TPM_PATH/${SWTPM}.pid SOCK_PATH=$TPM_PATH/sock CMD_PATH=$TPM_PATH/cmd RESP_PATH=$TPM_PATH/resp LOGFILE=$TPM_PATH/logfile function cleanup() { pid=$(ps aux | grep $SWTPM | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') if [ -n "$pid" ]; then kill_quiet -9 $pid fi rm -rf $TPM_PATH } trap "cleanup" EXIT source ${TESTDIR}/common source ${TESTDIR}/load_vtpm_proxy rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null $SWTPM_EXE chardev --vtpm-proxy \ --tpmstate dir=$TPM_PATH \ --ctrl type=unixio,path=$SOCK_PATH \ ${SWTPM_TEST_SECCOMP_OPT} \ --pid file=$PID_FILE &>$LOGFILE & sleep 0.5 PID=$(ps aux | grep $SWTPM | grep -E " file=${PID_FILE}\$" | gawk '{print $2}') display_processes_by_name "$SWTPM" kill_quiet -0 $PID if [ $? -ne 0 ]; then echo "Error: Chardev TPM did not start." exit 1 fi if wait_for_file $PID_FILE 3; then echo "Error: Chardev TPM did not write pidfile." exit 1 fi # Wait for chardev to appear; TPM 1.2 may take a long time to self-test # with valgrind for ((i = 0; i < 200; i ++)); do if [ -z "${TPM_DEVICE}" ]; then TPM_DEVICE=$(sed -n 's,.*\(/dev/tpm[0-9]\+\).*,\1,p' $LOGFILE) if [ -n "${TPM_DEVICE}" ]; then echo "Using ${TPM_DEVICE}." fi fi if [ -n "${TPM_DEVICE}" ]; then [ -c "${TPM_DEVICE}" ] && break fi sleep 0.1 done if ! [ -c "${TPM_DEVICE}" ]; then echo "Error: Chardev ${TPM_DEVICE} did not appear" exit 1 fi # Open access to the TPM exec 100<>$TPM_DEVICE if [ $? -ne 0 ]; then echo "Error: Could not open $TPM_DEVICE" exit 1 fi # Read PCR 17 -- this should give a fatal error response echo -en '\x00\xC1\x00\x00\x00\x0E\x00\x00\x00\x15\x00\x00\x00\x11' >&100 #RES=$(cat <&100 | od -t x1 -A n -w128) RES=$(od -t x1 -A n -w128 <&100) exp=' 00 c4 00 00 00 1e 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff' if [ "$RES" != "$exp" ]; then echo "Error: Did not get expected result from TPM_PCRRead(17)" echo "expected: $exp" echo "received: $RES" exit 1 fi exec 100>&- kill_quiet -0 $PID if [ $? -ne 0 ]; then echo "Error: Chardev TPM must have crashed." exit 1 fi if [ ! -e $STATE_FILE ]; then echo "Error: TPM state file $STATE_FILE does not exist." exit 1 fi # Send shutdown command to the TPM: CMD_SHUTDOWN = 00 00 00 03 echo -en '\x00\x00\x00\x03' > $CMD_PATH socat -x -t10 FILE:$CMD_PATH,rdonly UNIX-CONNECT:$SOCK_PATH 2>&1 | \ sed -n '/^ /p' | \ tail -n1 > $RESP_PATH res="$(cat $RESP_PATH)" exp=" 00 00 00 00" if [ "$res" != "$exp" ]; then echo "Error: Unexpected response from CMD_SHUTDOWN:" echo " actual : $res" echo " expected: $exp" exit 1 fi if wait_file_gone $PID_FILE 2; then echo "Error: TPM should have removed PID file by now." exit 1 fi if wait_process_gone ${PID} 4; then echo "Error: TPM should not be running anymore." exit 1 fi echo "OK" exit 0 swtpm-0.6.3/tests/test_wrongorder000077500000000000000000000014771421141172300172160ustar00rootroot00000000000000#!/usr/bin/env bash cd "$(dirname "$0")" export SWTPM_IOCTL_BUFFERSIZE=100 export SWTPM_INTERFACE=cuse bash _test_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_IOCTL_BUFFERSIZE=4096 export SWTPM_INTERFACE=cuse bash _test_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+socket export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65422 export SWTPM_CTRL_PORT=65423 bash _test_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=socket+unix export SWTPM_SERVER_NAME=localhost export SWTPM_SERVER_PORT=65422 bash _test_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret export SWTPM_INTERFACE=unix+unix bash _test_wrongorder ret=$? [ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret exit 0