pax_global_header00006660000000000000000000000064141246451650014522gustar00rootroot0000000000000052 comment=ebd59ef827f1fc8e0efa43f9cade4d3d7efee59a tpm2-tools-5.2/000077500000000000000000000000001412464516500134105ustar00rootroot00000000000000tpm2-tools-5.2/.ci/000077500000000000000000000000001412464516500140615ustar00rootroot00000000000000tpm2-tools-5.2/.ci/coverity.run000077500000000000000000000060121412464516500164550ustar00rootroot00000000000000#!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause set -eo pipefail export COV_PROJECT="01org/tpm2.0-tools" echo "COV_PROJECT=$COV_PROJECT" if [ -z "$COVERITY_SCAN_TOKEN" ]; then echo "coverity.run invoked without COVERITY_SCAN_TOKEN set...exiting!" exit 1 fi if [ -z "$COVERITY_SUBMISSION_EMAIL" ]; then echo "coverity.run invoked without COVERITY_SUBMISSION_EMAIL set...exiting!" exit 1 fi # Sanity check, this should only be executing on the coverity_scan branch if [[ "$REPO_BRANCH" != *coverity_scan ]]; then echo "coverity.run invoked for non-coverity branch $REPO_BRANCH...exiting!" exit 1 fi if [[ "$CC" == clang* ]]; then echo "Coverity scan branch detected, not running with clang...exiting!" exit 1 fi # branch is coverity_scan echo "Running coverity build" # ensure coverity_scan tool is available to the container # We cannot package these in the docker image, as we would be distributing their software # for folks not coupled to our COVERITY_SCAN_TOKEN. if [ ! -f "$(pwd)/cov-analysis/bin/cov-build" ]; then curl --data-urlencode "project=$COV_PROJECT" \ --data-urlencode "token=$COVERITY_SCAN_TOKEN" \ "https://scan.coverity.com/download/linux64" -o coverity_tool.tgz stat coverity_tool.tgz curl --data-urlencode "project=$COV_PROJECT" \ --data-urlencode "token=$COVERITY_SCAN_TOKEN" \ --data-urlencode "md5=1" \ "https://scan.coverity.com/download/linux64" -o coverity_tool.md5 stat coverity_tool.md5 cat coverity_tool.md5 md5sum coverity_tool.tgz echo "$(cat coverity_tool.md5)" coverity_tool.tgz | md5sum -c echo "unpacking cov-analysis" tar -xf coverity_tool.tgz mv cov-analysis-* cov-analysis fi export PATH=$PATH:$(pwd)/cov-analysis/bin echo "Which cov-build: $(which cov-build)" pushd "$DOCKER_BUILD_DIR" source ".ci/docker-prelude.sh" echo "Performing build with Coverity Scan" rm -rf cov-int ./bootstrap && ./configure --enable-debug && make clean cov-build --dir $DOCKER_BUILD_DIR/cov-int make -j $(nproc) echo "Collecting Coverity data for submission" rm -fr README AUTHOR="$(git log -1 $HEAD --pretty="%aN")" AUTHOR_EMAIL="$(git log -1 $HEAD --pretty="%aE")" VERSION="$(git rev-parse HEAD)" echo "Name: $AUTHOR" >> README echo "Email: $AUTHOR_EMAIL" >> README echo "Project: tpm2-tools" >> README echo "Build-Version: $VERSION" >> README echo "Description: $REPO_SLUG $REPO_BRANCH" >> README echo "Submitted-by: tpm2-tools CI" >> README echo "---README---" cat README echo "---EOF---" rm -f tpm2-tools-scan.tgz tar -czf tpm2-tools-scan.tgz README cov-int rm -rf README cov-int # upload the results echo "Testing for scan results..." scan_file=$(stat --printf='%n' tpm2-*-scan.tgz) echo "Submitting data to Coverity" curl --form token="$COVERITY_SCAN_TOKEN" \ --form email="$COVERITY_SUBMISSION_EMAIL" \ --form project="$COV_PROJECT" \ --form file=@"$scan_file" \ --form version="$VERSION" \ --form description="$REPO_SLUG $REPO_BRANCH" \ "https://scan.coverity.com/builds?project=01org%2Ftpm2.0-tools" rm -rf tpm2-*-scan.tgz popd exit 0 tpm2-tools-5.2/.ci/docker-prelude.sh000077500000000000000000000006601412464516500173270ustar00rootroot00000000000000#!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause # all command failures are fatal set -e WORKSPACE=`dirname $DOCKER_BUILD_DIR` echo "Workspace: $WORKSPACE" source $DOCKER_BUILD_DIR/.ci/download-deps.sh get_deps "$WORKSPACE" export LD_LIBRARY_PATH=/usr/local/lib/ export PATH=/root/.local/bin/:/ibmtpm974/src:$PATH echo "echo changing to $DOCKER_BUILD_DIR" # Change to the the travis build dir cd $DOCKER_BUILD_DIR tpm2-tools-5.2/.ci/docker.env000066400000000000000000000004031412464516500160370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause DOCKER_BUILD_DIR=/workspace/tpm2-tools CC COVERITY_SCAN_TOKEN COVERITY_SUBMISSION_EMAIL PROJECT REPO_BRANCH REPO_SLUG PYTHON_INTERPRETER ENABLE_COVERAGE ENABLE_FUZZING DOCKER_IMAGE TPM2_TSS_VERSION GIT_FULL_CLONE tpm2-tools-5.2/.ci/docker.run000077500000000000000000000104531412464516500160640ustar00rootroot00000000000000#!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause set -e source $DOCKER_BUILD_DIR/.ci/docker-prelude.sh if [ -d build ]; then rm -rf build fi # Do not run tests when building on coverity_scan branch if [ "${COVERITY_SCAN_BRANCH}" == 1 ]; then echo "Coverity scan branch detected, not running build nor tests...exiting!" exit 0 fi # If it's clang, enable asan if [[ "$CC" == clang* ]]; then echo "Detecting clang, enable asan" export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer" echo "Exported CFLAGS=$CFLAGS" config_flags="--disable-hardening" echo "Disabled configure option hardening" export ASAN_ENABLED=true echo "Exported ASAN_ENABLED=$ASAN_ENABLED" # To get line numbers set up the asan symbolizer clang_version=`$CC --version | head -n 1 | cut -d\ -f 3-3 | cut -d\. -f 1-2` # Sometimes the version string has an Ubuntu on the front of it and the field # location changes if [ $clang_version == "version" ]; then clang_version=`$CC --version | head -n 1 | cut -d\ -f 4-4 | cut -d\. -f 1-2` fi echo "Detected clang version: $clang_version" ASAN_SYMBOLIZER_PATH="/usr/lib/llvm-$clang_version/bin/llvm-symbolizer" if [ -e "$ASAN_SYMBOLIZER_PATH" ]; then export ASAN_SYMBOLIZER_PATH echo "Exported ASAN_SYMBOLIZER_PATH=$ASAN_SYMBOLIZER_PATH" else echo "No llvm symbolizer found at: $ASAN_SYMBOLIZER_PATH" unset ASAN_SYMBOLIZER_PATH fi else #GCC config_flags="--disable-hardening --enable-code-coverage" fi # Bootstrap in the tpm2.0-tss tools directory ./bootstrap # clang has asan enabled with options exported that fail # make distcheck, so only do this with gcc. # Do a make distcheck in the root, clear it and than # cd to the variant directory. if [[ "$CC" != clang* ]]; then ./configure make distcheck make distclean fi # Make a build variant directory and change to it mkdir ./build pushd ./build # Run scan-build for gcc only. # Scan-build does not work with clang because of asan linking errors. if [[ "$CC" != clang* ]]; then scan-build ../configure --enable-unit $config_flags scan-build --status-bugs make -j$(nproc) # scan-build causes test_tpm2_session to fail, so # rebuild after running scan-build. fi ../configure --enable-unit $config_flags make -j$(nproc) make -j check popd # # Backwards compatibility test for ensuring we do not break the tool options # determined in 4.X release. # if [[ "${TPM2_TSS_VERSION}" == "master" && "$CC" != clang* ]];then echo "tpm2-tools v4.X compatibility test follows" git fetch origin refs/tags/4.3.0:refs/tags/4.3.0 git checkout 4.3.0 test/integration/tests git clean -fdx tests/integration/fapi # # RSA OAEP decryption was enabled as a feature after 4.X and so testing it # would signal a false compatibility test failure. # git checkout HEAD test/integration/tests/rsadecrypt.sh # # tpm2_getekcertificate is known to break backwards compatibility # git checkout HEAD test/integration/tests/getekcertificate.sh # # symlink is an irrelevant test for 4.X branch # rm test/integration/tests/symlink.sh # # Beyond 4.X release, the tpm2-tools were combined into a single # busybox style binary "tpm2". The following makes adjustments # to the tool-name which essentially invokes the same tools. # for f in `find test/integration/tests -iname '*.sh'` do for i in `find tools -iname 'tpm2*.c'` do test=$(basename $i .c) replace=$(basename $i .c | sed 's/tpm2_//g') sed -i "s/$test/tpm2 $replace/g" $f done done ./bootstrap mkdir compatibility_testbuild pushd compatibility_testbuild ../configure --enable-unit --disable-fapi --disable-hardening --with-tpmsim=tpm_server make -j$(nproc) make check -j$(nproc) popd git reset --hard HEAD fi # back in root git directory, check for whitespace errors. We do this post CI # so people can verify the rest of their patch works in CI before dying. # git diff --check fails with a non-zero return code causing the shell to die # as it has a set -e executed. check_branch="origin/${TRAVIS_BRANCH:-master}" [ -z "$TRAVIS_TAG" ] && git fetch "$check_branch" && git diff --check "$check_branch" if [ "$ENABLE_COVERAGE" == "true" ]; then bash <(curl -s https://codecov.io/bash) else echo "ENABLE_COVERAGE not true, got \"$ENABLE_COVERAGE\"" fi exit 0 tpm2-tools-5.2/.ci/download-deps.sh000066400000000000000000000034401412464516500171560ustar00rootroot00000000000000#!/usr/bin/env bash # SPDX-License-Identifier: BSD-3-Clause function get_deps() { export TSS_VERSION=${TPM2_TSS_VERSION:-3.1.0} ABRMD_VERSION=2.4.0 EXTRA_CONFIG_FLAGS='' pkg_conf_path="$(pkg-config --variable pc_path pkg-config | cut -d: -f 1-1)" if [ "$pkg_conf_path" != "/usr/lib/pkgconfig" ]; then echo "Detected non-standard pkgconfig path: \"$pkg_conf_path\"" EXTRA_CONFIG_FLAGS="--with-pkgconfigdir=\"$pkg_conf_path\"" fi echo "pwd starting: `pwd`" if [ "$TSS_VERSION" = "2.4.0" ]; then if [ "$DOCKER_IMAGE" = "fedora-30" ]; then yum -y install libgcrypt-devel elif [ "$DOCKER_IMAGE" = "opensuse-leap" ]; then zypper -n in libgcrypt-devel elif [ "$DOCKER_IMAGE" = "ubuntu-20.04" -o "$DOCKER_IMAGE" = "ubuntu-18.04" ]; then apt-get -y install libgcrypt20-dev fi fi pushd "$1" echo "pwd clone tss: `pwd`" if [ ! -d tpm2-tss ]; then if [ -z "$GIT_FULL_CLONE" ]; then echo "Doing shallow clone of tss" git_extra_flags="--depth=1" else echo "Doing deep clone of tss" fi git clone $git_extra_flags \ --branch "$TSS_VERSION" https://github.com/tpm2-software/tpm2-tss.git pushd tpm2-tss echo "pwd build tss: `pwd`" ./bootstrap ./configure --disable-doxygen-doc $EXTRA_CONFIG_FLAGS CFLAGS=-g make -j4 make install popd echo "pwd done tss: `pwd`" else echo "tss already downloaded/built/installed, skipping" fi if [ ! -d tpm2-abrmd ]; then echo "pwd clone abrmd: `pwd`" git clone --depth=1 \ --branch "$ABRMD_VERSION" https://github.com/tpm2-software/tpm2-abrmd.git pushd tpm2-abrmd echo "pwd build abrmd: `pwd`" ./bootstrap ./configure $EXTRA_CONFIG_FLAGS CFLAGS=-g make -j4 make install popd echo "pwd done abrmd: `pwd`" popd echo "pwd done: `pwd`" else echo "abrmd already downloaded/built/installed, skipping" fi } tpm2-tools-5.2/.ci/travis.run000077500000000000000000000020601412464516500161200ustar00rootroot00000000000000#!/usr/bin/env bash set -e export PROJECT="tpm2-tools" # if no DOCKER_IMAGE is set, warn and default to fedora-30 if [ -z "$DOCKER_IMAGE" ]; then echo "WARN: DOCKER_IMAGE is not set, defaulting to fedora-30" export DOCKER_IMAGE="fedora-30" fi # # Docker starts you in a cloned repo of your project with the PR checkout out. # We want those changes IN the docker image, so use the -v option to mount the # project repo in the docker image. # # Also, pass in any env variables required for the build via .ci/docker.env file # # Execute the build and test procedure by running .ci/docker.run # ci_env="" if [ "$ENABLE_COVERAGE" == "true" ]; then ci_env=$(bash <(curl -s https://codecov.io/env)) fi if [ "$ENABLE_COVERITY" == "true" ]; then echo "Running coverity build" script="coverity.run" else echo "Running non-coverity build" script="docker.run" fi docker run --cap-add=SYS_PTRACE $ci_env --env-file .ci/docker.env \ -v "$(pwd):/workspace/$PROJECT" "ghcr.io/tpm2-software/$DOCKER_IMAGE" \ /bin/bash -c "/workspace/$PROJECT/.ci/$script" exit 0 tpm2-tools-5.2/.cirrus.yml000066400000000000000000000034371412464516500155270ustar00rootroot00000000000000task: env: CFLAGS: -I/usr/local/include LDFLAGS: -L/usr/local/lib LD_LIBRARY_PATH: /usr/local/lib PKG_CONFIG_PATH: "/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig" PATH: "${PATH}:/usr/local/sbin:/usr/sbin" ibmtpm_name: ibmtpm1637 TSS2_LOG: "all+ERROR;tcti+TRACE" freebsd_instance: image_family: freebsd-12-2 install_script: - pkg update -f - pkg upgrade -y - pkg install -y bash gmake coreutils libtool pkgconf autoconf autoconf-archive e2fsprogs-libuuid py38-yaml expect - pkg install -y automake glib dbus dbus-glib cmocka wget git openssl json-c vim - wget --quiet --show-progress --progress=dot:giga "https://downloads.sourceforge.net/project/ibmswtpm2/$ibmtpm_name.tar.gz" - shasum -a256 $ibmtpm_name.tar.gz | grep ^dd3a4c3f7724243bc9ebcd5c39bbf87b82c696d1c1241cb8e5883534f6e2e327 - mkdir -p $ibmtpm_name - tar xvf $ibmtpm_name.tar.gz -C $ibmtpm_name && cd $ibmtpm_name/src - sed -i '' -e 's/gcc/clang/g' makefile - sed -i '' -e 's/-Wall //g' makefile - sed -i '' -e 's/-Werror //g' makefile - gmake && cp tpm_server /usr/bin/ - cd - - rm -rf $ibmtpm_name $ibmtpm_name.tar.gz - mkdir tss - cd tss && git clone https://github.com/tpm2-software/tpm2-tss.git - cd tpm2-tss && ./bootstrap && ./configure --disable-doxygen-doc --disable-tcti-swtpm --disable-dependency-tracking && gmake -j install - cd ../../ && rm -rf tss - mkdir rm - cd rm && git clone https://github.com/tpm2-software/tpm2-abrmd.git && cd tpm2-abrmd - ./bootstrap && ./configure --disable-dependency-tracking && gmake -j install - cd ../../ && rm -rf rm script: - ./bootstrap - ./configure --enable-unit=yes --disable-dependency-tracking --disable-fapi - gmake -j check || { cat test-suite.log; exit 1; } tpm2-tools-5.2/.codecov.yml000066400000000000000000000001471412464516500156350ustar00rootroot00000000000000ignore: - test coverage: status: project: default: threshold: 1% patch: off tpm2-tools-5.2/.github/000077500000000000000000000000001412464516500147505ustar00rootroot00000000000000tpm2-tools-5.2/.github/workflows/000077500000000000000000000000001412464516500170055ustar00rootroot00000000000000tpm2-tools-5.2/.github/workflows/main.yml000066400000000000000000000045611412464516500204620ustar00rootroot00000000000000name: CI on: [push, pull_request] jobs: generic-build-test: runs-on: ubuntu-latest if: "!contains(github.ref, 'coverity_scan')" strategy: matrix: docker_image: [ubuntu-18.04, ubuntu-20.04, fedora-30, opensuse-leap, fedora-32] compiler: [gcc, clang] steps: - name: Check out repository uses: actions/checkout@v2 - name: Launch Container env: DOCKER_IMAGE: ${{ matrix.docker_image }} CC: ${{ matrix.compiler }} run: ./.ci/travis.run - name: failure if: ${{ failure() }} run: cat build/test-suite.log || true master-tss-build-test: runs-on: ubuntu-latest if: "!contains(github.ref, 'coverity_scan')" strategy: matrix: compiler: [gcc, clang] steps: - name: Check out repository uses: actions/checkout@v2 - name: Launch Container env: DOCKER_IMAGE: ubuntu-18.04 CC: ${{ matrix.compiler }} TPM2_TSS_VERSION: master GIT_FULL_CLONE: true run: ./.ci/travis.run - name: failure if: ${{ failure() }} run: cat build/test-suite.log || true coverage-test: runs-on: ubuntu-latest if: "!contains(github.ref, 'coverity_scan')" steps: - name: Check out repository uses: actions/checkout@v2 - name: Launch Container env: ENABLE_COVERAGE: true DOCKER_IMAGE: ubuntu-18.04 CC: gcc run: ./.ci/travis.run - name: failure cat build logs if: ${{ failure() }} run: cat build/test-suite.log || true - name: failure cat compatibility_testbuild logs if: ${{ failure() }} run: cat compatibility_testbuild/test-suite.log || true coverity-test: runs-on: ubuntu-latest if: contains(github.ref, 'coverity_scan') steps: - name: Check out repository uses: actions/checkout@v2 - name: Launch Container env: REPO_BRANCH: ${{ github.ref }} REPO_SLUG: ${{ github.repository }} ENABLE_COVERITY: true DOCKER_IMAGE: ubuntu-18.04 CC: gcc COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} COVERITY_SUBMISSION_EMAIL: william.c.roberts@gmail.com run: ./.ci/travis.run - name: failure if: ${{ failure() }} run: cat build/test-suite.log || true tpm2-tools-5.2/.gitignore000066400000000000000000000004011412464516500153730ustar00rootroot00000000000000.deps/ .dirstamp *.log *.trs aclocal.m4 aminclude_static.am autom4te.cache/ compile config.guess config.log config.status config.sub configure depcomp install-sh m4/ libtool ltmain.sh missing Makefile Makefile.in test-driver # dist tarball *.gz src_vars.mk tpm2-tools-5.2/.lgtm.yml000066400000000000000000000011431412464516500151530ustar00rootroot00000000000000extraction: cpp: prepare: packages: - autoconf-archive - libcurl4-openssl-dev - libjson-c-dev - libssl-dev - acl - git after_prepare: - cd "$LGTM_WORKSPACE" - mkdir installdir - git clone https://github.com/tpm2-software/tpm2-tss.git - cd tpm2-tss - ./bootstrap - ./configure --prefix="$LGTM_WORKSPACE/installdir/usr" --disable-doxygen-doc - make install - export PKG_CONFIG_PATH="$LGTM_WORKSPACE/installdir/usr/lib/pkgconfig:$PKG_CONFIG_PATH" - export LD_LIBRARY_PATH="$LGTM_WORKSPACE/installdir/usr/lib:$LD_LIBRARY_PATH" tpm2-tools-5.2/.readthedocs.yml000066400000000000000000000000611412464516500164730ustar00rootroot00000000000000version: 2 mkdocs: configuration: mkdocs.yml tpm2-tools-5.2/Makefile.am000066400000000000000000000532111412464516500154460ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause # ax_code_coverage if AUTOCONF_CODE_COVERAGE_2019_01_06 include $(top_srcdir)/aminclude_static.am clean-local: code-coverage-clean distclean-local: code-coverage-dist-clean else @CODE_COVERAGE_RULES@ endif include src_vars.mk ACLOCAL_AMFLAGS = -I m4 --install INCLUDE_DIRS = -I$(top_srcdir)/tools -I$(top_srcdir)/lib LIB_COMMON := lib/libcommon.a AM_CFLAGS := \ $(INCLUDE_DIRS) $(EXTRA_CFLAGS) $(TSS2_ESYS_CFLAGS) $(TSS2_MU_CFLAGS) \ $(CRYPTO_CFLAGS) $(CODE_COVERAGE_CFLAGS) $(TSS2_TCTILDR_CFLAGS) \ $(TSS2_RC_CFLAGS) $(TSS2_SYS_CFLAGS) AM_LDFLAGS := $(EXTRA_LDFLAGS) $(CODE_COVERAGE_LIBS) LDADD = \ $(LIB_COMMON) $(TSS2_ESYS_LIBS) $(TSS2_MU_LIBS) $(CRYPTO_LIBS) $(TSS2_TCTILDR_LIBS) \ $(TSS2_RC_LIBS) $(TSS2_SYS_LIBS) $(EFIVAR_LIBS) AM_DISTCHECK_CONFIGURE_FLAGS = --with-bashcompdir='$$(datarootdir)/bash-completion/completions' # keep me sorted bin_PROGRAMS = FAPI_CFLAGS = $(EXTRA_CFLAGS) $(TSS2_FAPI_CFLAGS) $(CODE_COVERAGE_CFLAGS) TESTS = if HAVE_FAPI bin_PROGRAMS += tools/fapi/tss2 endif noinst_LIBRARIES = $(LIB_COMMON) lib_libcommon_a_SOURCES = $(LIB_SRC) lib_libcommon_a_CFLAGS = -fPIC $(AM_CFLAGS) tools_fapi_tss2_CFLAGS = $(FAPI_CFLAGS) -DTSS2_TOOLS_MAX="$(words $(tss2_tools))" tools_fapi_tss2_LDFLAGS = $(EXTRA_LDFLAGS) $(TSS2_FAPI_LIBS) tools_fapi_tss2_SOURCES = \ tools/fapi/tss2_template.c \ tools/fapi/tss2_template.h \ $(tss2_tools) tss2_tools = \ tools/fapi/tss2_decrypt.c \ tools/fapi/tss2_encrypt.c \ tools/fapi/tss2_list.c \ tools/fapi/tss2_changeauth.c \ tools/fapi/tss2_delete.c \ tools/fapi/tss2_import.c \ tools/fapi/tss2_getinfo.c \ tools/fapi/tss2_createkey.c \ tools/fapi/tss2_createseal.c \ tools/fapi/tss2_exportkey.c \ tools/fapi/tss2_getcertificate.c \ tools/fapi/tss2_getplatformcertificates.c \ tools/fapi/tss2_gettpmblobs.c \ tools/fapi/tss2_getappdata.c \ tools/fapi/tss2_setappdata.c \ tools/fapi/tss2_setcertificate.c \ tools/fapi/tss2_sign.c \ tools/fapi/tss2_verifysignature.c \ tools/fapi/tss2_verifyquote.c \ tools/fapi/tss2_createnv.c \ tools/fapi/tss2_nvextend.c \ tools/fapi/tss2_nvincrement.c \ tools/fapi/tss2_nvread.c \ tools/fapi/tss2_nvsetbits.c \ tools/fapi/tss2_nvwrite.c \ tools/fapi/tss2_getdescription.c \ tools/fapi/tss2_setdescription.c \ tools/fapi/tss2_pcrextend.c \ tools/fapi/tss2_quote.c \ tools/fapi/tss2_pcrread.c \ tools/fapi/tss2_authorizepolicy.c \ tools/fapi/tss2_exportpolicy.c \ tools/fapi/tss2_import.c \ tools/fapi/tss2_provision.c \ tools/fapi/tss2_getrandom.c \ tools/fapi/tss2_unseal.c \ tools/fapi/tss2_writeauthorizenv.c # Bundle all the tools into a single program similar to busybox bin_PROGRAMS += tools/tpm2 tools_tpm2_LDADD = $(LDADD) $(CURL_LIBS) tools_tpm2_CFLAGS = $(AM_CFLAGS) -DTPM2_TOOLS_MAX="$(words $(tpm2_tools))" tools_tpm2_SOURCES = \ tools/tpm2_tool.c \ tools/tpm2_tool.h \ $(tpm2_tools) tpm2_tools = \ tools/misc/tpm2_certifyX509certutil.c \ tools/misc/tpm2_checkquote.c \ tools/misc/tpm2_eventlog.c \ tools/misc/tpm2_print.c \ tools/misc/tpm2_rc_decode.c \ tools/tpm2_activatecredential.c \ tools/tpm2_certify.c \ tools/tpm2_changeauth.c \ tools/tpm2_changeeps.c \ tools/tpm2_changepps.c \ tools/tpm2_clear.c \ tools/tpm2_clearcontrol.c \ tools/tpm2_clockrateadjust.c \ tools/tpm2_create.c \ tools/tpm2_createak.c \ tools/tpm2_createek.c \ tools/tpm2_createpolicy.c \ tools/tpm2_setprimarypolicy.c \ tools/tpm2_createprimary.c \ tools/tpm2_dictionarylockout.c \ tools/tpm2_duplicate.c \ tools/tpm2_getcap.c \ tools/tpm2_gettestresult.c \ tools/tpm2_encryptdecrypt.c \ tools/tpm2_evictcontrol.c \ tools/tpm2_flushcontext.c \ tools/tpm2_getekcertificate.c \ tools/tpm2_getrandom.c \ tools/tpm2_gettime.c \ tools/tpm2_hash.c \ tools/tpm2_hierarchycontrol.c \ tools/tpm2_hmac.c \ tools/tpm2_import.c \ tools/tpm2_incrementalselftest.c \ tools/tpm2_load.c \ tools/tpm2_loadexternal.c \ tools/tpm2_makecredential.c \ tools/tpm2_nvdefine.c \ tools/tpm2_nvextend.c \ tools/tpm2_nvincrement.c \ tools/tpm2_nvreadpublic.c \ tools/tpm2_nvread.c \ tools/tpm2_nvreadlock.c \ tools/tpm2_nvundefine.c \ tools/tpm2_nvwrite.c \ tools/tpm2_nvwritelock.c \ tools/tpm2_nvsetbits.c \ tools/tpm2_pcrallocate.c \ tools/tpm2_pcrevent.c \ tools/tpm2_pcrextend.c \ tools/tpm2_pcrread.c \ tools/tpm2_pcrreset.c \ tools/tpm2_policypcr.c \ tools/tpm2_policyauthorize.c \ tools/tpm2_policyauthorizenv.c \ tools/tpm2_policynv.c \ tools/tpm2_policycountertimer.c \ tools/tpm2_policyor.c \ tools/tpm2_policynamehash.c \ tools/tpm2_policytemplate.c \ tools/tpm2_policycphash.c \ tools/tpm2_policypassword.c \ tools/tpm2_policysigned.c \ tools/tpm2_policyticket.c \ tools/tpm2_policyauthvalue.c \ tools/tpm2_policysecret.c \ tools/tpm2_policyrestart.c \ tools/tpm2_policycommandcode.c \ tools/tpm2_policynvwritten.c \ tools/tpm2_policyduplicationselect.c \ tools/tpm2_policylocality.c \ tools/tpm2_quote.c \ tools/tpm2_readclock.c \ tools/tpm2_readpublic.c \ tools/tpm2_rsadecrypt.c \ tools/tpm2_rsaencrypt.c \ tools/tpm2_send.c \ tools/tpm2_selftest.c \ tools/tpm2_setclock.c \ tools/tpm2_shutdown.c \ tools/tpm2_sign.c \ tools/tpm2_certifycreation.c \ tools/tpm2_nvcertify.c \ tools/tpm2_startauthsession.c \ tools/tpm2_startup.c \ tools/tpm2_stirrandom.c \ tools/tpm2_testparms.c \ tools/tpm2_unseal.c \ tools/tpm2_verifysignature.c \ tools/tpm2_setcommandauditstatus.c \ tools/tpm2_getcommandauditdigest.c \ tools/tpm2_getsessionauditdigest.c \ tools/tpm2_geteccparameters.c \ tools/tpm2_ecephemeral.c \ tools/tpm2_commit.c \ tools/tpm2_ecdhkeygen.c \ tools/tpm2_ecdhzgen.c \ tools/tpm2_zgen2phase.c \ tools/tpm2_sessionconfig.c \ tools/tpm2_getpolicydigest.c # Create the symlinks for each tool to the tpm2 and optional tss2 bundled executables install-exec-hook: for tool in $(notdir $(basename $(tpm2_tools))) ; do \ $(LN_S) -f \ "tpm2$(EXEEXT)" \ "$(DESTDIR)$(bindir)/$$tool$(EXEEXT)" ; \ done if HAVE_FAPI for tool in $(notdir $(basename $(tss2_tools))) ; do \ $(LN_S) -f \ "tss2$(EXEEXT)" \ "$(DESTDIR)$(bindir)/$$tool$(EXEEXT)" ; \ done endif if UNIT TESTS += $(check_PROGRAMS) check_PROGRAMS = \ test/unit/test_string_bytes \ test/unit/test_files \ test/unit/test_tpm2_header \ test/unit/test_tpm2_attr_util \ test/unit/test_tpm2_alg_util \ test/unit/test_pcr \ test/unit/test_tpm2_auth_util \ test/unit/test_tpm2_errata \ test/unit/test_tpm2_session \ test/unit/test_tpm2_policy \ test/unit/test_tpm2_util \ test/unit/test_options \ test/unit/test_cc_util \ test/unit/test_tpm2_eventlog \ test/unit/test_tpm2_eventlog_yaml TESTS += $(ALL_SYSTEM_TESTS) if HAVE_FAPI TESTS += $(ALL_FAPI_TESTS) endif test_unit_test_string_bytes_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_string_bytes_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_files_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_files_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_header_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_header_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_attr_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_attr_util_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_alg_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_alg_util_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_pcr_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_pcr_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_auth_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_auth_util_LDFLAGS = -Wl,--wrap=Esys_TR_SetAuth \ -Wl,--wrap=Esys_StartAuthSession \ -Wl,--wrap=fopen \ -Wl,--wrap=fread \ -Wl,--wrap=fseek \ -Wl,--wrap=ftell \ -Wl,--wrap=feof, \ -Wl,--wrap=fclose test_unit_test_tpm2_auth_util_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_errata_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_errata_LDFLAGS = -Wl,--wrap=Esys_GetCapability test_unit_test_tpm2_errata_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_session_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_session_LDFLAGS = -Wl,--wrap=Esys_StartAuthSession \ -Wl,--wrap=tpm2_context_save \ -Wl,--wrap=Esys_ContextLoad \ -Wl,--wrap=Esys_PolicyRestart \ -Wl,--wrap=Esys_TR_GetName \ -Wl,--wrap=tpm2_flush_context test_unit_test_tpm2_session_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_policy_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_policy_LDFLAGS = -Wl,--wrap=Esys_StartAuthSession \ -Wl,--wrap=Esys_PolicyPCR \ -Wl,--wrap=Esys_PCR_Read \ -Wl,--wrap=Esys_PolicyGetDigest \ -Wl,--wrap=Esys_FlushContext test_unit_test_tpm2_policy_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_util_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_options_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_options_LDFLAGS = -Wl,--wrap=Tss2_TctiLdr_Initialize \ -Wl,--wrap=tpm2_util_getenv test_unit_test_options_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_cc_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_cc_util_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_eventlog_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_eventlog_LDADD = $(CMOCKA_LIBS) $(LDADD) test_unit_test_tpm2_eventlog_yaml_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS) test_unit_test_tpm2_eventlog_yaml_LDADD = $(CMOCKA_LIBS) $(LDADD) AM_TESTS_ENVIRONMENT = \ export TPM2_ABRMD=$(TPM2_ABRMD); \ export TPM2_SIM=$(TPM2_SIM); \ export PATH=$(abs_builddir)/tools:$(abs_builddir)/tools/misc:$(abs_top_srcdir)/test/integration:$(abs_builddir)/tools/fapi:$(PATH); \ export TPM2_TOOLS_TEST_FIXTURES=$(abs_top_srcdir)/test/integration/fixtures; \ export abs_builddir=$(abs_builddir); \ export abs_srcdir=$(abs_srcdir); \ export PYTHON=$(PYTHON); \ export TPM2_TOOLS_TEST_FIXTURES; if PERSISTENT AM_TESTS_ENVIRONMENT += \ TPM2TOOLS_TEST_PERSISTENT=true; else AM_TESTS_ENVIRONMENT += \ TPM2TOOLS_TEST_PERSISTENT=false; endif SH_LOG_COMPILER = dbus-run-session bash AM_SH_LOG_FLAGS = -- endif TEST_EXTENSIONS = .sh check-hook: rm -rf .lock_file EXTRA_DIST_IGNORE = \ .gitignore \ .deps EXTRA_DIST = \ bootstrap \ doc/AUTHORS.md \ doc/CHANGELOG.md \ doc/CONTRIBUTING.md \ doc/INSTALL.md \ doc/LICENSE \ doc/MAINTAINERS.md \ doc/README.md \ doc/RELEASE.md \ man \ scripts \ test if HAVE_MAN_PAGES dist_man1_MANS := \ man/man1/tpm2_activatecredential.1 \ man/man1/tpm2_certify.1 \ man/man1/tpm2_certifyX509certutil.1 \ man/man1/tpm2_changeauth.1 \ man/man1/tpm2_changeeps.1 \ man/man1/tpm2_changepps.1 \ man/man1/tpm2_checkquote.1 \ man/man1/tpm2_clear.1 \ man/man1/tpm2_clearcontrol.1 \ man/man1/tpm2_clockrateadjust.1 \ man/man1/tpm2_create.1 \ man/man1/tpm2_createak.1 \ man/man1/tpm2_createek.1 \ man/man1/tpm2_createpolicy.1 \ man/man1/tpm2_setprimarypolicy.1 \ man/man1/tpm2_createprimary.1 \ man/man1/tpm2_dictionarylockout.1 \ man/man1/tpm2_duplicate.1 \ man/man1/tpm2_getcap.1 \ man/man1/tpm2_encryptdecrypt.1 \ man/man1/tpm2_eventlog.1 \ man/man1/tpm2_evictcontrol.1 \ man/man1/tpm2_flushcontext.1 \ man/man1/tpm2_getekcertificate.1 \ man/man1/tpm2_getrandom.1 \ man/man1/tpm2_gettestresult.1 \ man/man1/tpm2_gettime.1 \ man/man1/tpm2_hierarchycontrol.1 \ man/man1/tpm2_hash.1 \ man/man1/tpm2_hmac.1 \ man/man1/tpm2_import.1 \ man/man1/tpm2_incrementalselftest.1 \ man/man1/tpm2_load.1 \ man/man1/tpm2_loadexternal.1 \ man/man1/tpm2_makecredential.1 \ man/man1/tpm2_nvdefine.1 \ man/man1/tpm2_nvextend.1 \ man/man1/tpm2_nvincrement.1 \ man/man1/tpm2_nvreadpublic.1 \ man/man1/tpm2_nvread.1 \ man/man1/tpm2_nvreadlock.1 \ man/man1/tpm2_nvundefine.1 \ man/man1/tpm2_nvwrite.1 \ man/man1/tpm2_nvwritelock.1 \ man/man1/tpm2_nvsetbits.1 \ man/man1/tpm2_pcrallocate.1 \ man/man1/tpm2_pcrevent.1 \ man/man1/tpm2_pcrextend.1 \ man/man1/tpm2_pcrread.1 \ man/man1/tpm2_pcrreset.1 \ man/man1/tpm2_policypcr.1 \ man/man1/tpm2_policyrestart.1 \ man/man1/tpm2_policycommandcode.1 \ man/man1/tpm2_policynvwritten.1 \ man/man1/tpm2_policyduplicationselect.1 \ man/man1/tpm2_policylocality.1 \ man/man1/tpm2_policyauthorize.1 \ man/man1/tpm2_policyauthorizenv.1 \ man/man1/tpm2_policynv.1 \ man/man1/tpm2_policycountertimer.1 \ man/man1/tpm2_policyor.1 \ man/man1/tpm2_policynamehash.1 \ man/man1/tpm2_policytemplate.1 \ man/man1/tpm2_policycphash.1 \ man/man1/tpm2_policypassword.1 \ man/man1/tpm2_policysigned.1 \ man/man1/tpm2_policyticket.1 \ man/man1/tpm2_policyauthvalue.1 \ man/man1/tpm2_policysecret.1 \ man/man1/tpm2_print.1 \ man/man1/tpm2_quote.1 \ man/man1/tpm2_rc_decode.1 \ man/man1/tpm2_readclock.1 \ man/man1/tpm2_readpublic.1 \ man/man1/tpm2_rsadecrypt.1 \ man/man1/tpm2_rsaencrypt.1 \ man/man1/tpm2_send.1 \ man/man1/tpm2_selftest.1 \ man/man1/tpm2_setclock.1 \ man/man1/tpm2_shutdown.1 \ man/man1/tpm2_sign.1 \ man/man1/tpm2_certifycreation.1 \ man/man1/tpm2_nvcertify.1 \ man/man1/tpm2_startauthsession.1 \ man/man1/tpm2_startup.1 \ man/man1/tpm2_stirrandom.1 \ man/man1/tpm2_testparms.1 \ man/man1/tpm2_unseal.1 \ man/man1/tpm2_verifysignature.1 \ man/man1/tpm2_setcommandauditstatus.1 \ man/man1/tpm2_getcommandauditdigest.1 \ man/man1/tpm2_getsessionauditdigest.1 \ man/man1/tpm2_geteccparameters.1 \ man/man1/tpm2_ecephemeral.1 \ man/man1/tpm2_commit.1 \ man/man1/tpm2_ecdhkeygen.1 \ man/man1/tpm2_ecdhzgen.1 \ man/man1/tpm2_zgen2phase.1 \ man/man1/tpm2_sessionconfig.1 \ man/man1/tpm2_getpolicydigest.1 \ man/man1/tpm2.1 if HAVE_FAPI dist_man1_MANS += \ man/man1/tss2_list.1 \ man/man1/tss2_changeauth.1 \ man/man1/tss2_delete.1 \ man/man1/tss2_import.1 \ man/man1/tss2_decrypt.1 \ man/man1/tss2_encrypt.1 \ man/man1/tss2_getinfo.1 \ man/man1/tss2_createnv.1 \ man/man1/tss2_nvread.1 \ man/man1/tss2_nvextend.1 \ man/man1/tss2_nvincrement.1 \ man/man1/tss2_nvsetbits.1 \ man/man1/tss2_nvwrite.1 \ man/man1/tss2_createkey.1 \ man/man1/tss2_createseal.1 \ man/man1/tss2_getcertificate.1 \ man/man1/tss2_getplatformcertificates.1 \ man/man1/tss2_gettpmblobs.1 \ man/man1/tss2_getappdata.1 \ man/man1/tss2_setappdata.1 \ man/man1/tss2_setcertificate.1 \ man/man1/tss2_exportkey.1 \ man/man1/tss2_sign.1 \ man/man1/tss2_verifysignature.1 \ man/man1/tss2_verifyquote.1 \ man/man1/tss2_getdescription.1 \ man/man1/tss2_setdescription.1 \ man/man1/tss2_pcrextend.1 \ man/man1/tss2_quote.1 \ man/man1/tss2_pcrread.1 \ man/man1/tss2_provision.1 \ man/man1/tss2_authorizepolicy.1 \ man/man1/tss2_exportpolicy.1 \ man/man1/tss2_unseal.1 \ man/man1/tss2_import.1 \ man/man1/tss2_getrandom.1 \ man/man1/tss2_writeauthorizenv.1 endif endif MARKDOWN_COMMON_DEPS = \ man/common/alg.md \ man/common/authorizations.md \ man/common/ctxobj.md \ man/common/footer.md \ man/common/hash.md \ man/common/obj-attrs.md \ man/common/object-alg.md \ man/common/options.md \ man/common/pcrs_format.md \ man/common/policy-limitations.md \ man/common/pubkey.md \ man/common/returns.md \ man/common/signature.md \ man/common/signschemes.md \ man/common/tcti.md man/man1/%.1 : man/%.1.md $(MARKDOWN_COMMON_DEPS) $(AM_V_GEN)rm -f $@ && \ mkdir -p man/man1 && \ sed -e '/\[common options\]/r $(top_srcdir)/man/common/options.md' \ -e '/\[common options\]/d' \ -e '/\[common tcti options\]/r $(top_srcdir)/man/common/tcti.md' \ -e '/\[common tcti options\]/d' \ -e '/\[common tss2 options\]/r $(top_srcdir)/man/common/tss2-options.md' \ -e '/\[common tss2 options\]/d' \ -e '/\[common fapi references\]/r $(top_srcdir)/man/common/tss2-fapi-references.md' \ -e '/\[common fapi references\]/d' \ -e '/\[authorization formatting\]/r $(top_srcdir)/man/common/authorizations.md' \ -e '/\[authorization formatting\]/d' \ -e '/\[context object format\]/r $(top_srcdir)/man/common/ctxobj.md' \ -e '/\[context object format\]/d' \ -e '/\[supported hash algorithms\]/r $(top_srcdir)/man/common/hash.md' \ -e '/\[supported hash algorithms\]/d' \ -e '/\[algorithm specifiers\]/r $(top_srcdir)/man/common/alg.md' \ -e '/\[algorithm specifiers\]/d' \ -e '/\[supported public object algorithms\]/r $(top_srcdir)/man/common/object-alg.md' \ -e '/\[supported public object algorithms\]/d' \ -e '/\[supported signing algorithms\]/r $(top_srcdir)/man/common/sign-alg.md' \ -e '/\[supported signing algorithms\]/d' \ -e '/\[nv attributes\]/r $(top_srcdir)/man/common/nv-attrs.md' \ -e '/\[nv attributes\]/d' \ -e '/\[pcr bank specifiers\]/r $(top_srcdir)/man/common/pcr.md' \ -e '/\[pcr bank specifiers\]/d' \ -e '/\[PCR output file format specifiers\]/r $(top_srcdir)/man/common/pcrs_format.md' \ -e '/\[PCR output file format specifiers\]/d' \ -e '/\[pubkey options\]/r $(top_srcdir)/man/common/pubkey.md' \ -e '/\[pubkey options\]/d' \ -e '/\[signature format specifiers\]/r $(top_srcdir)/man/common/signature.md' \ -e '/\[signature format specifiers\]/d' \ -e '/\[object attribute specifiers\]/r $(top_srcdir)/man/common/obj-attrs.md' \ -e '/\[object attribute specifiers\]/d' \ -e '/\[supported signing schemes\]/r $(top_srcdir)/man/common/signschemes.md' \ -e '/\[supported signing schemes\]/d' \ -e '/\[limitations\]/r $(top_srcdir)/man/common/policy-limitations.md' \ -e '/\[limitations\]/d' \ -e '/\[returns\]/r $(top_srcdir)/man/common/returns.md' \ -e '/\[returns\]/d' \ -e '/\[footer\]/r $(top_srcdir)/man/common/footer.md' \ -e '/\[footer\]/d' \ -e '/\[protection details\]/r $(top_srcdir)/man/common/protection-details.md' \ -e '/\[protection details\]/d' \ < $< | pandoc -s -t man > $@ CLEANFILES = $(dist_man1_MANS) bashcompdir=@bashcompdir@ dist_bashcomp_DATA=dist/bash-completion/tpm2-tools/tpm2_completion.bash if HAVE_FAPI dist_bashcomp_DATA+= \ dist/bash-completion/tpm2-tools/tss2_decrypt \ dist/bash-completion/tpm2-tools/tss2_encrypt \ dist/bash-completion/tpm2-tools/tss2_list \ dist/bash-completion/tpm2-tools/tss2_changeauth \ dist/bash-completion/tpm2-tools/tss2_delete \ dist/bash-completion/tpm2-tools/tss2_import \ dist/bash-completion/tpm2-tools/tss2_getinfo \ dist/bash-completion/tpm2-tools/tss2_createkey \ dist/bash-completion/tpm2-tools/tss2_createseal \ dist/bash-completion/tpm2-tools/tss2_exportkey \ dist/bash-completion/tpm2-tools/tss2_getcertificate \ dist/bash-completion/tpm2-tools/tss2_getplatformcertificates \ dist/bash-completion/tpm2-tools/tss2_gettpmblobs \ dist/bash-completion/tpm2-tools/tss2_setcertificate \ dist/bash-completion/tpm2-tools/tss2_getappdata \ dist/bash-completion/tpm2-tools/tss2_setappdata \ dist/bash-completion/tpm2-tools/tss2_sign \ dist/bash-completion/tpm2-tools/tss2_verifysignature \ dist/bash-completion/tpm2-tools/tss2_verifyquote \ dist/bash-completion/tpm2-tools/tss2_createnv \ dist/bash-completion/tpm2-tools/tss2_nvextend \ dist/bash-completion/tpm2-tools/tss2_nvincrement \ dist/bash-completion/tpm2-tools/tss2_nvread \ dist/bash-completion/tpm2-tools/tss2_nvsetbits \ dist/bash-completion/tpm2-tools/tss2_nvwrite \ dist/bash-completion/tpm2-tools/tss2_getdescription \ dist/bash-completion/tpm2-tools/tss2_setdescription \ dist/bash-completion/tpm2-tools/tss2_pcrextend \ dist/bash-completion/tpm2-tools/tss2_quote \ dist/bash-completion/tpm2-tools/tss2_pcrread \ dist/bash-completion/tpm2-tools/tss2_authorizepolicy \ dist/bash-completion/tpm2-tools/tss2_exportpolicy \ dist/bash-completion/tpm2-tools/tss2_provision \ dist/bash-completion/tpm2-tools/tss2_getrandom \ dist/bash-completion/tpm2-tools/tss2_unseal \ dist/bash-completion/tpm2-tools/tss2_writeauthorizenv \ dist/bash-completion/tpm2-tools/tss2 endif install-data-hook: cd $(DESTDIR)$(bashcompdir) && \ for tool in $(bin_PROGRAMS); do \ [ "$${tool}" = "$${tool#tools/fapi/*}" ] && $(LN_S) -f tpm2_completion.bash $${tool##*/}; \ done uninstall-hook: cd $(DESTDIR)$(bashcompdir) && \ for tool in $(bin_PROGRAMS); do \ [ "$${tool}" = "$${tool#tools/fapi/*}" -a -L $${tool##*/} ] && rm -f $${tool##*/}; \ done dist-hook: for f in $(EXTRA_DIST_IGNORE); do \ rm -rf `find $(distdir) -name $$f`; \ done; if !HAVE_PANDOC # If pandoc is not enabled, we want to complain that you need pandoc for make dist, # so hook the target and complain. @(>&2 echo "You do not have pandoc, a requirement for the distribution of manpages") @exit 1 endif tpm2-tools-5.2/README.md000066400000000000000000000017721412464516500146760ustar00rootroot00000000000000[![Build Status](https://github.com/tpm2-software/tpm2-tools/workflows/CI/badge.svg)](https://github.com/tpm2-software/tpm2-tools/actions) [![FreeBSD Build Status](https://api.cirrus-ci.com/github/tpm2-software/tpm2-tools.svg?branch=master)](https://cirrus-ci.com/github/tpm2-software/tpm2-tools) [![codecov](https://codecov.io/gh/tpm2-software/tpm2-tools/branch/master/graph/badge.svg)](https://codecov.io/gh/tpm2-software/tpm2-tools) [![Coverity Scan](https://img.shields.io/coverity/scan/3997.svg)](https://scan.coverity.com/projects/01org-tpm2-0-tools) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/tpm2-software/tpm2-tools.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/tpm2-software/tpm2-tools/context:cpp) # tpm2-tools The source repository for the Trusted Platform Module (TPM2.0) tools based on [tpm2-software/tpm2-tss](https://github.com/tpm2-software/tpm2-tss) [Readthedocs](https://tpm2-tools.readthedocs.io/en/latest/) for information on installation, man-pages and more. tpm2-tools-5.2/bootstrap000077500000000000000000000022371412464516500153570ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: BSD-3-Clause set -e # generate list of source files for use in Makefile.am # if you add new source files, you must run ./bootstrap again src_listvar () { basedir=$1 suffix=$2 var=$3 find "${basedir}" -name "${suffix}" | LC_ALL=C sort | tr '\n' ' ' | (printf "${var} = " && cat) echo "" } # duplicate fapi tests with ecc duplicate () { basedir=$1 suffix=$2 find "${basedir}" \( -iname "${suffix}" ! -iname "*ecc.sh" \) | while read fname; do cp $fname ${fname%.sh}_ecc.sh sed -i -e 's/CRYPTO_PROFILE="RSA"/CRYPTO_PROFILE="ECC"/g' ${fname%.sh}_ecc.sh done } VARS_FILE=src_vars.mk AUTORECONF=${AUTORECONF:-autoreconf} echo "Generating file lists: ${VARS_FILE}" ( src_listvar "lib" "*.c" "LIB_C" src_listvar "lib" "*.h" "LIB_H" printf "LIB_SRC = \$(LIB_C) \$(LIB_H)\n" src_listvar "test/integration/tests" "*.sh" "SYSTEM_TESTS" printf "ALL_SYSTEM_TESTS = \$(SYSTEM_TESTS)\n" duplicate "test/integration/fapi" "*.sh" src_listvar "test/integration/fapi" "*.sh" "FAPI_TESTS" printf "ALL_FAPI_TESTS = \$(FAPI_TESTS)\n" ) > ${VARS_FILE} mkdir -p m4 ${AUTORECONF} --install --sym tpm2-tools-5.2/configure.ac000066400000000000000000000261611412464516500157040ustar00rootroot00000000000000AC_INIT([tpm2-tools], [m4_esyscmd_s([git describe --tags --always --dirty])]) AC_CONFIG_MACRO_DIR([m4]) AX_IS_RELEASE([dash-version]) AX_CHECK_ENABLE_DEBUG([info]) AC_PROG_CC AC_PROG_LN_S LT_INIT AM_INIT_AUTOMAKE([foreign subdir-objects]) # enable "silent-rules" option by default m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AX_CODE_COVERAGE m4_ifdef([_AX_CODE_COVERAGE_RULES], [AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [true])], [AM_CONDITIONAL(AUTOCONF_CODE_COVERAGE_2019_01_06, [false])]) AX_ADD_AM_MACRO_STATIC([]) AC_CONFIG_FILES([Makefile]) # enable autoheader config.h file AC_CONFIG_HEADERS([lib/config.h]) AC_CHECK_PROG([PANDOC],[pandoc],[yes]) AS_IF( [test "x${PANDOC}" = x"yes"], [], [AC_MSG_WARN([Required executable pandoc not found, man pages will not be built])]) AM_CONDITIONAL([HAVE_PANDOC],[test "x${PANDOC}" = "xyes"]) AM_CONDITIONAL( [HAVE_MAN_PAGES], [test -d "${srcdir}/man/man1" -o "x${PANDOC}" = "xyes"]) AC_ARG_ENABLE([fapi], [AS_HELP_STRING([--disable-fapi], [disable FAPI tools (default: auto)])],, [enable_fapi=check]) AS_IF([test "$enable_fapi" = yes -o "$enable_fapi" = check], [PKG_CHECK_MODULES([TSS2_FAPI], [tss2-fapi], [enable_fapi=yes], [ AS_IF([test "$enable_fapi" = yes], [AC_MSG_ERROR([Required module tss2-fapi not found])]) enable_fapi=no ]) PKG_CHECK_MODULES([TSS2_FAPI_3_0], [tss2-fapi >= 3.0], [AC_DEFINE([FAPI_3_0], [1], [fapi3.0.0])], [true]) ]) AM_CONDITIONAL([HAVE_FAPI], [test "$enable_fapi" = yes]) PKG_CHECK_MODULES([TSS2_ESYS_3_0], [tss2-esys >= 3.0.0], [AC_DEFINE([ESYS_3_0], [1], [Esys3.0])] [AC_SUBST([TSS2_ESYS_CFLAGS], [$TSS2_ESYS_3_0_CFLAGS]) AC_SUBST([TSS2_ESYS_LIBS], [$TSS2_ESYS_3_0_LIBS])], [PKG_CHECK_MODULES([TSS2_ESYS_2_3], [tss2-esys >= 2.4.0], [AC_DEFINE([ESYS_2_3], [1], [Esys2.3])] [AC_SUBST([TSS2_ESYS_CFLAGS], [$TSS2_ESYS_2_3_CFLAGS]) AC_SUBST([TSS2_ESYS_LIBS], [$TSS2_ESYS_2_3_LIBS])])]) PKG_CHECK_MODULES([TSS2_TCTILDR], [tss2-tctildr]) PKG_CHECK_MODULES([TSS2_MU], [tss2-mu]) PKG_CHECK_MODULES([TSS2_RC], [tss2-rc]) PKG_CHECK_MODULES([TSS2_SYS], [tss2-sys]) PKG_CHECK_MODULES([CRYPTO], [libcrypto >= 1.1.0]) PKG_CHECK_MODULES([CURL], [libcurl]) # pretty print of devicepath if efivar library is present PKG_CHECK_MODULES([EFIVAR], [efivar],,[true]) AC_CHECK_HEADERS([efivar/efivar.h]) # backwards compat with older pkg-config # - pull in AC_DEFUN from pkg.m4 m4_ifndef([PKG_CHECK_VAR], [ # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # ------------------------------------------- # Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR ]) AC_ARG_WITH([bashcompdir], AS_HELP_STRING([--with-bashcompdir=DIR], [directory for bash completions]), , [PKG_CHECK_VAR([with_bashcompdir], [bash-completion], [completionsdir], , [with_bashcompdir="${datarootdir}/bash-completion/completions"])]) AC_SUBST(bashcompdir, [$with_bashcompdir]) AC_ARG_WITH([tpmsim], AS_HELP_STRING([--with-tpmsim=BIN], [simulator used for testing]), [], []) AC_SUBST(tpmsim, [$with_tpmsim]) AC_CANONICAL_HOST # Check OS and set library and compile flags accordingly case "${host_os}" in *nto-qnx*) EXTRA_CFLAGS="$EXTRA_CFLAGS -D_QNX_SOURCE" LIBDL_LDFLAGS="" ;; *) LIBDL_LDFLAGS="-ldl" ;; esac AC_SUBST([LIBDL_LDFLAGS]) AC_ARG_ENABLE([unit], [AS_HELP_STRING([--enable-unit], [build cmocka unit tests])],, [enable_unit=no]) AM_CONDITIONAL([UNIT], [test "x$enable_unit" != xno]) AC_ARG_ENABLE([persistent], [AS_HELP_STRING([--disable-persistent], [disable tests that require resetting the TPM])],,) AM_CONDITIONAL([PERSISTENT], [test "x$enable_persistent" != xno]) dnl macro that checks for specific modules in python AC_DEFUN([AC_PYTHON_MODULE], [AC_MSG_CHECKING([for module $1 in $PYTHON]) echo "import $1" | $PYTHON - 2>/dev/null if test $? -ne 0 ; then AC_MSG_ERROR([not found]) else AC_MSG_RESULT(found) fi ]) # Check OS and set library and compile flags accordingly case "${host_os}" in *bsd* | *BSD*) HOSTOS='BSD' ;; *) #Assume linux HOSTOS='Linux' ;; esac AS_IF([test "x$enable_unit" != xno], [ PKG_CHECK_MODULES([CMOCKA],[cmocka]) AC_CHECK_PROG([tpm2_abrmd], [tpm2-abrmd], yes, no) AS_IF([test $tpm2_abrmd = yes], [TPM2_ABRMD=tpm2-abrmd], [AC_MSG_ERROR([Required executable tpm2_abrmd not found, try setting PATH])] ) AC_SUBST([TPM2_ABRMD]) AS_IF([test -z "$tpmsim"], [ AC_CHECK_PROG([swtpm], [swtpm], yes, no) AC_CHECK_PROG([tpm_server], [tpm_server], yes, no) AS_IF([test $swtpm = yes], [TPM2_SIM=swtpm], [AS_IF([test $tpm_server = yes], [TPM2_SIM=tpm_server], [AC_MSG_ERROR([Required executables swtpm or tpm_server not found, try setting PATH])])]) ], [ AC_CHECK_PROG([HAS_TPM2_SIM], [$tpmsim], yes, no) AS_IF([test "$HAS_TPM2_SIM" = yes], [TPM2_SIM=$tpmsim], [AC_MSG_ERROR([Required executable $tpmsim not found, system tests require a tpm simulator shell!])] ) ] ) AC_SUBST([TPM2_SIM]) AC_CHECK_PROG([BASH_SHELL], [bash], yes, no) AS_IF([test $BASH_SHELL = no], [AC_MSG_ERROR([Required executable bash not found, system tests require a bash shell!])]) AM_PATH_PYTHON([], [], [AC_MSG_ERROR([Required executable python not found, some system tests will fail!])] ) AC_PYTHON_MODULE([yaml]) AC_CHECK_PROG([XXD], [xxd], yes, no) AS_IF([test $XXD = no], [AC_MSG_ERROR([Required executable xxd not found, some system tests will fail!])]) AS_IF([test "$HOSTOS" = "Linux"], [AC_CHECK_PROG([SS], [ss], [yes], [no])], [AC_CHECK_PROG([SS], [sockstat], [yes], [no])]) AS_IF([test $SS = no], [AC_MSG_ERROR([Required executable ss/sockstat not found, some system tests will fail!])]) AC_CHECK_PROG([SHASUM], [shasum], yes, no) AS_IF([test $SHASUM = no], [AC_MSG_ERROR([Required executable shasum not found, some system tests will fail!])]) AC_CHECK_PROG([MKTEMP], [mktemp], yes, no) AS_IF([test $MKTEMP = no], [AC_MSG_ERROR([Required executable mktemp not found, some system tests will fail!])]) AC_CHECK_PROG([EXPECT], [expect], yes, no) AS_IF([test $EXPECT = no], [AC_MSG_ERROR([Required executable expect not found, some system tests will fail!])]) AC_CHECK_PROG([OPENSSL], [openssl], yes, no) AS_IF([test $OPENSSL = no], [AC_MSG_ERROR([Required executable openssl not found, some system tests will fail!])]) unit_test_tool_report="- tpm2_abrmd: $tpm2_abrmd - TPM simulator: $TPM2_SIM - bash: $BASH_SHELL - python: $PYTHON - xxd: $XXD - ss: $SS - shasum: $SHASUM - mktemp: $MKTEMP - expect: $EXPECT - openssl: $OPENSSL" ]) AC_ARG_ENABLE([dlclose], [AS_HELP_STRING([--disable-dlclose], [Some versions of libc cause a sigsegv on exit, this disables the dlclose and works around that bug])], [AC_DEFINE([DISABLE_DLCLOSE], [1], [Some versions of libc cause a sigsegv on exit with dlclose(), this disables the dlclose() and works around that bug])] ) AC_ARG_ENABLE([hardening], [AS_HELP_STRING([--disable-hardening], [Disable compiler and linker options to frustrate memory corruption exploits])],, [enable_hardening="yes"]) # Good information on adding flags, and dealing with compilers can be found here: # https://github.com/zcash/zcash/issues/1832 # https://github.com/kmcallister/autoharden/ AS_IF([test x"$enable_hardening" != x"no"], [ AC_DEFUN([add_hardened_c_flag], [ AX_CHECK_COMPILE_FLAG([$1], [EXTRA_CFLAGS="$EXTRA_CFLAGS $1"], [AC_MSG_ERROR([Cannot enable $1, consider configuring with --disable-hardening])] ) ]) AC_DEFUN([add_hardened_ld_flag], [ AX_CHECK_LINK_FLAG([$1], [EXTRA_LDFLAGS="$EXTRA_LDFLAGS $1"], [AC_MSG_ERROR([Cannot enable $1, consider configuring with --disable-hardening])] ) ]) AC_DEFUN([add_hardened_define_flag], [ AX_CHECK_PREPROC_FLAG([$1], [EXTRA_CFLAGS="$EXTRA_CFLAGS $1"], [AC_MSG_ERROR([Cannot enable $1, consider configuring with --disable-hardening])] ) ]) add_hardened_c_flag([-Wall]) add_hardened_c_flag([-Wextra]) AS_IF([test "x$ax_is_release" = "xno"], [add_hardened_c_flag([-Werror])]) add_hardened_c_flag([-Wformat]) add_hardened_c_flag([-Wformat-security]) add_hardened_c_flag([-Wstack-protector]) add_hardened_c_flag([-fstack-protector-all]) add_hardened_c_flag([-Wstrict-overflow=5]) add_hardened_c_flag([-O2]) AX_ADD_FORTIFY_SOURCE add_hardened_c_flag([-fPIC]) add_hardened_ld_flag([[-shared]]) add_hardened_c_flag([-fPIE]) add_hardened_ld_flag([[-pie]]) add_hardened_ld_flag([[-Wl,-z,relro]]) add_hardened_ld_flag([[-Wl,-z,now]]) ], [ AC_MSG_WARN([Compiling with --disable-hardening is dangerous! you should consider fixing the configure script compiler flags and submitting patches upstream!]) ]) AC_DEFUN([add_c_flag], [ AX_CHECK_COMPILE_FLAG([$1], [EXTRA_CFLAGS="$EXTRA_CFLAGS $1"], $2 ) ]) # -D_GNU_SOURCE is required for execvpe() in options.c add_c_flag([-D_GNU_SOURCE], [AC_MSG_ERROR([Cannot enable -D_GNU_SOURCE])]) # Enable gnu99 mode, since we use some of these features. add_c_flag([-std=gnu99], [AC_MSG_ERROR([Cannot enable -std=gnu99])]) # Best attempt compiler options that are on newer versions of GCC that # we can't widely enforce without killing other peoples builds. # Works with gcc only. Needs to be disabled on BSD and clang AS_IF([test "$HOSTOS" = "Linux"], [add_c_flag([-Wstringop-overflow=4]) add_c_flag([-Wstringop-truncation]) add_c_flag([-Wduplicated-branches]) add_c_flag([-Wduplicated-cond]) add_c_flag([-Wbool-compare])],[]) # Best attempt, strip unused stuff from the binary to reduce size. # Rather than nesting these and making them ugly just use a counter. AX_CHECK_COMPILE_FLAG([-fdata-sections], [strip="${strip}y"]) AX_CHECK_COMPILE_FLAG([-ffunction-sections], [strip="${strip}y"]) AX_CHECK_LINK_FLAG([[-Wl,--gc-sections]], [strip="${strip}y"]) AS_IF([test x"$strip" = x"yyy"], [ EXTRA_CFLAGS="$EXTRA_CFLAGS -fdata-sections -ffunction-sections" EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,--gc-sections" ], AC_MSG_NOTICE([Not using compiler options to reduce binary size!]) ) AC_SUBST([EXTRA_CFLAGS]) AC_SUBST([EXTRA_LDFLAGS]) AC_SUBST([PATH]) AC_OUTPUT AC_MSG_RESULT([ - $PACKAGE_NAME: $VERSION - Man pages: ${PANDOC:-no} - Unit tests: $enable_unit $unit_test_tool_report ]) tpm2-tools-5.2/dist/000077500000000000000000000000001412464516500143535ustar00rootroot00000000000000tpm2-tools-5.2/dist/bash-completion/000077500000000000000000000000001412464516500174375ustar00rootroot00000000000000tpm2-tools-5.2/dist/bash-completion/tpm2-tools/000077500000000000000000000000001412464516500214575ustar00rootroot00000000000000tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tpm2_completion.bash000066400000000000000000005627231412464516500254500ustar00rootroot00000000000000# bash completion for tpm2_activatecredential -*- shell-script -*- _tpm2_activatecredential() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --credentialedkey-context) _filedir return;; -C | --credentialkey-context) _filedir return;; -p | --credentialedkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -P | --credentialkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -i | --credential-blob) _filedir return;; -o | --certinfo-data) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -C -p -P -i -o --credentialedkey-context --credentialkey-context --credentialedkey-auth --credentialkey-auth --credential-blob --certinfo-data --cphash " \ -- "$cur")) } && complete -F _tpm2_activatecredential tpm2_activatecredential # ex: filetype=sh # bash completion for tpm2_certify -*- shell-script -*- _tpm2_certify() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --certifiedkey-context) _filedir return;; -C | --signingkey-context) _filedir return;; -p | --certifiedkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -P | --signingkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -o | --attestation) _filedir return;; -s | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -C -p -g -P -o -s -f --certifiedkey-context --signingkey-context --certifiedkey-auth --hash-algorithm --signingkey-auth --attestation --signature --format --cphash " \ -- "$cur")) } && complete -F _tpm2_certify tpm2_certify # ex: filetype=sh # bash completion for tpm2_certifyX509certutil -*- shell-script -*- _tpm2_certifyX509certutil() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --outcert) _filedir return;; -d | --days) _filedir return;; -i | --issuer) _filedir return;; -s | --subject) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -o -d -i -s --outcert --days --issuer --subject " \ -- "$cur")) } && complete -F _tpm2_certifyX509certutil tpm2_certifyX509certutil # ex: filetype=sh # bash completion for tpm2_certifycreation -*- shell-script -*- _tpm2_certifycreation() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --signingkey-context) _filedir return;; -P | --signingkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --certifiedkey-context) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -d | --creation-hash) _filedir return;; -t | --ticket) _filedir return;; -o | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -q | --qualification) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -c -g -s -d -t -o -f -q --signingkey-context --signingkey-auth --certifiedkey-context --hash-algorithm --scheme --creation-hash --ticket --signature --format --qualification --cphash " \ -- "$cur")) } && complete -F _tpm2_certifycreation tpm2_certifycreation # ex: filetype=sh # bash completion for tpm2_changeauth -*- shell-script -*- _tpm2_changeauth() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --object-context) _filedir return;; -p | --object-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -C | --parent-context) _filedir return;; -r | --private) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -C -r --object-context --object-auth --parent-context --private --cphash " \ -- "$cur")) } && complete -F _tpm2_changeauth tpm2_changeauth # ex: filetype=sh # bash completion for tpm2_changeeps -*- shell-script -*- _tpm2_changeeps() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -p --auth " \ -- "$cur")) } && complete -F _tpm2_changeeps tpm2_changeeps # ex: filetype=sh # bash completion for tpm2_changepps -*- shell-script -*- _tpm2_changepps() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -p --auth " \ -- "$cur")) } && complete -F _tpm2_changepps tpm2_changepps # ex: filetype=sh # bash completion for tpm2_checkquote -*- shell-script -*- _tpm2_checkquote() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -u | --public) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -m | --message) _filedir return;; -s | --signature) _filedir return;; -f | --pcr) _filedir return;; -l | --pcr-list) _filedir return;; -q | --qualification) _filedir return;; -F | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -u -g -m -s -f -l -q -F --public --hash-algorithm --message --signature --pcr --pcr-list --qualification --format " \ -- "$cur")) } && complete -F _tpm2_checkquote tpm2_checkquote # ex: filetype=sh # bash completion for tpm2_clear -*- shell-script -*- _tpm2_clear() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --auth-hierarchy) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c --auth-hierarchy --cphash " \ -- "$cur")) } && complete -F _tpm2_clear tpm2_clear # ex: filetype=sh # bash completion for tpm2_clearcontrol -*- shell-script -*- _tpm2_clearcontrol() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P --hierarchy --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_clearcontrol tpm2_clearcontrol # ex: filetype=sh # bash completion for tpm2_clockrateadjust -*- shell-script -*- _tpm2_clockrateadjust() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --hierarchy) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p --hierarchy --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_clockrateadjust tpm2_clockrateadjust # ex: filetype=sh # bash completion for tpm2_commit -*- shell-script -*- _tpm2_commit() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -u | --public) _filedir return;; -t | --counter) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --context) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -u -t -p -c --public --counter --auth --context --basepoint --eccpoint --eccpoint --eccpoint " \ -- "$cur")) } && complete -F _tpm2_commit tpm2_commit # ex: filetype=sh # bash completion for tpm2_create -*- shell-script -*- _tpm2_create() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --parent-context) _filedir return;; -P | --parent-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --key-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -a | --attributes) COMPREPLY=($(compgen -W "${key_attributes[*]}" -- "$cur")) return;; -i | --sealing-input) _filedir return;; -L | --policy) _filedir return;; -u | --public) _filedir return;; -r | --private) _filedir return;; -c | --key-context) _filedir return;; -t | --creation-ticket) _filedir return;; -d | --creation-hash) _filedir return;; -q | --outside-info) _filedir return;; -l | --pcr-list) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -p -g -G -a -i -L -u -r -c -t -d -q -l --parent-context --parent-auth --key-auth --hash-algorithm --key-algorithm --attributes --sealing-input --policy --public --private --key-context --creation-ticket --creation-hash --outside-info --pcr-list --creation --template --cphash " \ -- "$cur")) } && complete -F _tpm2_create tpm2_create # ex: filetype=sh # bash completion for tpm2_createak -*- shell-script -*- _tpm2_createak() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --eh-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --ak-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -C | --ek-context) _filedir return;; -c | --ak-context) _filedir return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --signing-algorithm) _filedir return;; -u | --public) _filedir return;; -n | --ak-name) _filedir return;; -r | --private) _filedir return;; -q | --ak-qualified-name) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P -p -C -c -G -g -s -u -n -r -q --eh-auth --ak-auth --ek-context --ak-context --key-algorithm --hash-algorithm --signing-algorithm --public --ak-name --private --ak-qualified-name " \ -- "$cur")) } && complete -F _tpm2_createak tpm2_createak # ex: filetype=sh # bash completion for tpm2_createek -*- shell-script -*- _tpm2_createek() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --eh-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -w | --owner-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --ek-context) _filedir return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -u | --public) _filedir return;; -t | --template) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P -w -c -G -u -t --eh-auth --owner-auth --ek-context --key-algorithm --public --template " \ -- "$cur")) } && complete -F _tpm2_createek tpm2_createek # ex: filetype=sh # bash completion for tpm2_createpolicy -*- shell-script -*- _tpm2_createpolicy() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -g | --policy-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -l | --pcr-list) _filedir return;; -f | --pcr) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -g -l -f --policy --policy-algorithm --pcr-list --pcr --policy --policy " \ -- "$cur")) } && complete -F _tpm2_createpolicy tpm2_createpolicy # ex: filetype=sh # bash completion for tpm2_createprimary -*- shell-script -*- _tpm2_createprimary() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --key-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; -L | --policy) _filedir return;; -a | --attributes) COMPREPLY=($(compgen -W "${key_attributes[*]}" -- "$cur")) return;; -u | --unique-data) _filedir return;; -t | --creation-ticket) _filedir return;; -d | --creation-hash) _filedir return;; -q | --outside-info) _filedir return;; -l | --pcr-list) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -p -g -G -c -L -a -u -t -d -q -l --hierarchy --hierarchy-auth --key-auth --hash-algorithm --key-algorithm --key-context --policy --attributes --unique-data --creation-ticket --creation-hash --outside-info --pcr-list --creation --template --cphash " \ -- "$cur")) } && complete -F _tpm2_createprimary tpm2_createprimary # ex: filetype=sh # bash completion for tpm2_dictionarylockout -*- shell-script -*- _tpm2_dictionarylockout() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -s | --setup-parameters) _filedir return;; -c | --clear-lockout) _filedir return;; -l | --lockout-recovery-time) _filedir return;; -t | --recovery-time) _filedir return;; -n | --max-tries) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -s -c -l -t -n -p --setup-parameters --clear-lockout --lockout-recovery-time --recovery-time --max-tries --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_dictionarylockout tpm2_dictionarylockout # ex: filetype=sh # bash completion for tpm2_duplicate -*- shell-script -*- _tpm2_duplicate() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -G | --wrapper-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -i | --encryptionkey-in) _filedir return;; -o | --encryptionkey-out) _filedir return;; -C | --parent-context) _filedir return;; -r | --private) _filedir return;; -s | --encrypted-seed) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -G -i -o -C -r -s -p -c --wrapper-algorithm --encryptionkey-in --encryptionkey-out --parent-context --private --encrypted-seed --auth --key-context --cphash " \ -- "$cur")) } && complete -F _tpm2_duplicate tpm2_duplicate # ex: filetype=sh # bash completion for tpm2_ecdhkeygen -*- shell-script -*- _tpm2_ecdhkeygen() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --context) _filedir return;; -u | --public) _filedir return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -u -o --context --public --output " \ -- "$cur")) } && complete -F _tpm2_ecdhkeygen tpm2_ecdhkeygen # ex: filetype=sh # bash completion for tpm2_ecdhzgen -*- shell-script -*- _tpm2_ecdhzgen() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --key-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -u | --public) _filedir return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -u -o --key-context --key-auth --public --output " \ -- "$cur")) } && complete -F _tpm2_ecdhzgen tpm2_ecdhzgen # ex: filetype=sh # bash completion for tpm2_ecephemeral -*- shell-script -*- _tpm2_ecephemeral() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -u | --public) _filedir return;; -t | --counter) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -u -t --public --counter " \ -- "$cur")) } && complete -F _tpm2_ecephemeral tpm2_ecephemeral # ex: filetype=sh # bash completion for tpm2_encryptdecrypt -*- shell-script -*- _tpm2_encryptdecrypt() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -d | --decrypt) _filedir return;; -e | --pad) _filedir return;; -o | --output) _filedir return;; -G | --mode) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -t | --iv) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -d -e -o -G -t --key-context --auth --decrypt --pad --output --mode --iv --cphash " \ -- "$cur")) } && complete -F _tpm2_encryptdecrypt tpm2_encryptdecrypt # ex: filetype=sh # bash completion for tpm2_eventlog -*- shell-script -*- _tpm2_eventlog() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_eventlog tpm2_eventlog # ex: filetype=sh # bash completion for tpm2_evictcontrol -*- shell-script -*- _tpm2_evictcontrol() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -c | --object-context) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -c -P -o --hierarchy --object-context --auth --output --cphash " \ -- "$cur")) } && complete -F _tpm2_evictcontrol tpm2_evictcontrol # ex: filetype=sh # bash completion for tpm2_flushcontext -*- shell-script -*- _tpm2_flushcontext() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -t | --transient-object) _filedir return;; -l | --loaded-session) _filedir return;; -s | --saved-session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -t -l -s --transient-object --loaded-session --saved-session " \ -- "$cur")) } && complete -F _tpm2_flushcontext tpm2_flushcontext # ex: filetype=sh # bash completion for tpm2_getcap -*- shell-script -*- _tpm2_getcap() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -l | --list) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -l --list " \ -- "$cur")) } && complete -F _tpm2_getcap tpm2_getcap # ex: filetype=sh # bash completion for tpm2_getcommandauditdigest -*- shell-script -*- _tpm2_getcommandauditdigest() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -q | --qualification) _filedir return;; -s | --signature) _filedir return;; -m | --message) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P -c -p -q -s -m -f -g --hierarchy-auth --key-context --auth --qualification --signature --message --format --hash-algorithm " \ -- "$cur")) } && complete -F _tpm2_getcommandauditdigest tpm2_getcommandauditdigest # ex: filetype=sh # bash completion for tpm2_geteccparameters -*- shell-script -*- _tpm2_geteccparameters() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -o --output " \ -- "$cur")) } && complete -F _tpm2_geteccparameters tpm2_geteccparameters # ex: filetype=sh # bash completion for tpm2_getekcertificate -*- shell-script -*- _tpm2_getekcertificate() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --ek-certificate) _filedir return;; -X | --allow-unverified) _filedir return;; -u | --ek-public) _filedir return;; -x | --offline) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -o -X -u -x --ek-certificate --allow-unverified --ek-public --offline " \ -- "$cur")) } && complete -F _tpm2_getekcertificate tpm2_getekcertificate # ex: filetype=sh # bash completion for tpm2_getrandom -*- shell-script -*- _tpm2_getrandom() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --output) _filedir return;; -f | --force) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -o -f -S --output --force --session --hex --cphash --rphash " \ -- "$cur")) } && complete -F _tpm2_getrandom tpm2_getrandom # ex: filetype=sh # bash completion for tpm2_getsessionauditdigest -*- shell-script -*- _tpm2_getsessionauditdigest() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -q | --qualification) _filedir return;; -s | --signature) _filedir return;; -m | --message) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P -c -p -q -s -m -f -g -S --hierarchy-auth --key-context --auth --qualification --signature --message --format --hash-algorithm --session " \ -- "$cur")) } && complete -F _tpm2_getsessionauditdigest tpm2_getsessionauditdigest # ex: filetype=sh # bash completion for tpm2_gettestresult -*- shell-script -*- _tpm2_gettestresult() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_gettestresult tpm2_gettestresult # ex: filetype=sh # bash completion for tpm2_gettime -*- shell-script -*- _tpm2_gettime() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -P | --endorse-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -q | --qualification) _filedir return;; -o | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -P -g -s -q -o -f --key-context --auth --endorse-auth --hash-algorithm --scheme --qualification --signature --format --cphash " \ -- "$cur")) } && complete -F _tpm2_gettime tpm2_gettime # ex: filetype=sh # bash completion for tpm2_hash -*- shell-script -*- _tpm2_hash() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -o | --output) _filedir return;; -t | --ticket) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -g -o -t --hierarchy --hash-algorithm --output --ticket --hex " \ -- "$cur")) } && complete -F _tpm2_hash tpm2_hash # ex: filetype=sh # bash completion for tpm2_hierarchycontrol -*- shell-script -*- _tpm2_hierarchycontrol() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P --hierarchy --hierarchy-auth --cphash " \ -- "$cur")) } && complete -F _tpm2_hierarchycontrol tpm2_hierarchycontrol # ex: filetype=sh # bash completion for tpm2_hmac -*- shell-script -*- _tpm2_hmac() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -o | --output) _filedir return;; -t | --ticket) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -g -o -t --key-context --auth --hash-algorithm --output --ticket --hex --cphash " \ -- "$cur")) } && complete -F _tpm2_hmac tpm2_hmac # ex: filetype=sh # bash completion for tpm2_import -*- shell-script -*- _tpm2_import() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -i | --input) _filedir return;; -C | --parent-context) _filedir return;; -U | --parent-public) _filedir return;; -k | --encryption-key) _filedir return;; -r | --private) _filedir return;; -u | --public) _filedir return;; -a | --attributes) COMPREPLY=($(compgen -W "${key_attributes[*]}" -- "$cur")) return;; -P | --parent-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --key-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -s | --seed) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -G -g -i -C -U -k -r -u -a -P -p -L -s --key-algorithm --hash-algorithm --input --parent-context --parent-public --encryption-key --private --public --attributes --parent-auth --key-auth --policy --seed --passin --cphash " \ -- "$cur")) } && complete -F _tpm2_import tpm2_import # ex: filetype=sh # bash completion for tpm2_incrementalselftest -*- shell-script -*- _tpm2_incrementalselftest() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_incrementalselftest tpm2_incrementalselftest # ex: filetype=sh # bash completion for tpm2_load -*- shell-script -*- _tpm2_load() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --parent-context) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -u | --public) _filedir return;; -r | --private) _filedir return;; -n | --name) _filedir return;; -c | --key-context) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -u -r -n -c --parent-context --auth --public --private --name --key-context --cphash " \ -- "$cur")) } && complete -F _tpm2_load tpm2_load # ex: filetype=sh # bash completion for tpm2_loadexternal -*- shell-script -*- _tpm2_loadexternal() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -u | --public) _filedir return;; -r | --private) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -a | --attributes) COMPREPLY=($(compgen -W "${key_attributes[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; -n | --name) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -G -u -r -p -L -g -a -c -n --hierarchy --key-algorithm --public --private --auth --policy --hash-algorithm --attributes --key-context --name --passin " \ -- "$cur")) } && complete -F _tpm2_loadexternal tpm2_loadexternal # ex: filetype=sh # bash completion for tpm2_makecredential -*- shell-script -*- _tpm2_makecredential() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -e | --encryption-key) _filedir return;; -u | --public) _filedir return;; -G | --key-algorithm) COMPREPLY=($(compgen -W "${key_object[*]}" -- "$cur")) return;; -s | --secret) _filedir return;; -n | --name) _filedir return;; -o | --credential-blob) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -e -u -G -s -n -o --encryption-key --public --key-algorithm --secret --name --credential-blob " \ -- "$cur")) } && complete -F _tpm2_makecredential tpm2_makecredential # ex: filetype=sh # bash completion for tpm2_nvcertify -*- shell-script -*- _tpm2_nvcertify() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --signingkey-context) _filedir return;; -P | --signingkey-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --nvauthobj-context) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --nvauthobj-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -o | --signature) _filedir return;; -q | --qualification) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -c -p -g -s -f -o -q --signingkey-context --signingkey-auth --nvauthobj-context --nvauthobj-auth --hash-algorithm --scheme --format --signature --qualification --size --offset --cphash " \ -- "$cur")) } && complete -F _tpm2_nvcertify tpm2_nvcertify # ex: filetype=sh # bash completion for tpm2_nvdefine -*- shell-script -*- _tpm2_nvdefine() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -s | --size) _filedir return;; -a | --attributes) COMPREPLY=($(compgen -W "${nv_attributes[*]}" -- "$cur")) return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -p | --index-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -s -a -P -p -L --hierarchy --size --attributes --hierarchy-auth --index-auth --policy --hash-algorithm --cphash " \ -- "$cur")) } && complete -F _tpm2_nvdefine tpm2_nvdefine # ex: filetype=sh # bash completion for tpm2_nvextend -*- shell-script -*- _tpm2_nvextend() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -i | --input) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -i --hierarchy --auth --input --cphash " \ -- "$cur")) } && complete -F _tpm2_nvextend tpm2_nvextend # ex: filetype=sh # bash completion for tpm2_nvincrement -*- shell-script -*- _tpm2_nvincrement() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P --hierarchy --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_nvincrement tpm2_nvincrement # ex: filetype=sh # bash completion for tpm2_nvread -*- shell-script -*- _tpm2_nvread() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -o | --output) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -s | --size) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -o -P -s --hierarchy --output --auth --size --offset --cphash " \ -- "$cur")) } && complete -F _tpm2_nvread tpm2_nvread # ex: filetype=sh # bash completion for tpm2_nvreadlock -*- shell-script -*- _tpm2_nvreadlock() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P --hierarchy --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_nvreadlock tpm2_nvreadlock # ex: filetype=sh # bash completion for tpm2_nvreadpublic -*- shell-script -*- _tpm2_nvreadpublic() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_nvreadpublic tpm2_nvreadpublic # ex: filetype=sh # bash completion for tpm2_nvsetbits -*- shell-script -*- _tpm2_nvsetbits() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -i | --bits) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -i --hierarchy --auth --bits --cphash " \ -- "$cur")) } && complete -F _tpm2_nvsetbits tpm2_nvsetbits # ex: filetype=sh # bash completion for tpm2_nvundefine -*- shell-script -*- _tpm2_nvundefine() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -S --hierarchy --auth --session --cphash " \ -- "$cur")) } && complete -F _tpm2_nvundefine tpm2_nvundefine # ex: filetype=sh # bash completion for tpm2_nvwrite -*- shell-script -*- _tpm2_nvwrite() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -i | --input) _filedir return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -i -C -P --input --hierarchy --auth --offset --cphash " \ -- "$cur")) } && complete -F _tpm2_nvwrite tpm2_nvwrite # ex: filetype=sh # bash completion for tpm2_nvwritelock -*- shell-script -*- _tpm2_nvwritelock() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P --hierarchy --auth --global --cphash " \ -- "$cur")) } && complete -F _tpm2_nvwritelock tpm2_nvwritelock # ex: filetype=sh # bash completion for tpm2_pcrallocate -*- shell-script -*- _tpm2_pcrallocate() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P --auth " \ -- "$cur")) } && complete -F _tpm2_pcrallocate tpm2_pcrallocate # ex: filetype=sh # bash completion for tpm2_pcrevent -*- shell-script -*- _tpm2_pcrevent() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -P --auth " \ -- "$cur")) } && complete -F _tpm2_pcrevent tpm2_pcrevent # ex: filetype=sh # bash completion for tpm2_pcrextend -*- shell-script -*- _tpm2_pcrextend() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_pcrextend tpm2_pcrextend # ex: filetype=sh # bash completion for tpm2_pcrread -*- shell-script -*- _tpm2_pcrread() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local pcr_format_methods=(values serialized) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --output) _filedir return;; -F | --pcrs_format) COMPREPLY=($(compgen -W "${pcr_format_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -F --pcrs_format \ -o --output " \ -- "$cur")) } && complete -F _tpm2_pcrread tpm2_pcrread # ex: filetype=sh # bash completion for tpm2_pcrreset -*- shell-script -*- _tpm2_pcrreset() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_pcrreset tpm2_pcrreset # ex: filetype=sh # bash completion for tpm2_policyauthorize -*- shell-script -*- _tpm2_policyauthorize() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -i | --input) _filedir return;; -q | --qualification) _filedir return;; -n | --name) _filedir return;; -t | --ticket) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S -i -q -n -t --policy --session --input --qualification --name --ticket " \ -- "$cur")) } && complete -F _tpm2_policyauthorize tpm2_policyauthorize # ex: filetype=sh # bash completion for tpm2_policyauthorizenv -*- shell-script -*- _tpm2_policyauthorizenv() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -L -S --hierarchy --auth --policy --session --cphash " \ -- "$cur")) } && complete -F _tpm2_policyauthorizenv tpm2_policyauthorizenv # ex: filetype=sh # bash completion for tpm2_policyauthvalue -*- shell-script -*- _tpm2_policyauthvalue() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S --policy --session " \ -- "$cur")) } && complete -F _tpm2_policyauthvalue tpm2_policyauthvalue # ex: filetype=sh # bash completion for tpm2_policycommandcode -*- shell-script -*- _tpm2_policycommandcode() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -S | --session) _filedir return;; -L | --policy) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -S -L --session --policy " \ -- "$cur")) } && complete -F _tpm2_policycommandcode tpm2_policycommandcode # ex: filetype=sh # bash completion for tpm2_policycountertimer -*- shell-script -*- _tpm2_policycountertimer() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S --policy --session " \ -- "$cur")) } && complete -F _tpm2_policycountertimer tpm2_policycountertimer # ex: filetype=sh # bash completion for tpm2_policycphash -*- shell-script -*- _tpm2_policycphash() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S --policy --session --cphash " \ -- "$cur")) } && complete -F _tpm2_policycphash tpm2_policycphash # ex: filetype=sh # bash completion for tpm2_policyduplicationselect -*- shell-script -*- _tpm2_policyduplicationselect() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -S | --session) _filedir return;; -n | --object-name) _filedir return;; -N | --parent-name) _filedir return;; -L | --policy) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -S -n -N -L --session --object-name --parent-name --policy --include " \ -- "$cur")) } && complete -F _tpm2_policyduplicationselect tpm2_policyduplicationselect # ex: filetype=sh # bash completion for tpm2_policylocality -*- shell-script -*- _tpm2_policylocality() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -S | --session) _filedir return;; -L | --policy) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -S -L --session --policy " \ -- "$cur")) } && complete -F _tpm2_policylocality tpm2_policylocality # ex: filetype=sh # bash completion for tpm2_policynamehash -*- shell-script -*- _tpm2_policynamehash() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -n | --name) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S -n --policy --session --name " \ -- "$cur")) } && complete -F _tpm2_policynamehash tpm2_policynamehash # ex: filetype=sh # bash completion for tpm2_policynv -*- shell-script -*- _tpm2_policynv() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -i | --input) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -L -S -i --hierarchy --auth --policy --session --input --offset --cphash " \ -- "$cur")) } && complete -F _tpm2_policynv tpm2_policynv # ex: filetype=sh # bash completion for tpm2_policynvwritten -*- shell-script -*- _tpm2_policynvwritten() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -S | --session) _filedir return;; -L | --policy) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -S -L --session --policy " \ -- "$cur")) } && complete -F _tpm2_policynvwritten tpm2_policynvwritten # ex: filetype=sh # bash completion for tpm2_policyor -*- shell-script -*- _tpm2_policyor() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -l | --policy-list) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S -l --policy --session --policy-list " \ -- "$cur")) } && complete -F _tpm2_policyor tpm2_policyor # ex: filetype=sh # bash completion for tpm2_policypassword -*- shell-script -*- _tpm2_policypassword() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S --policy --session " \ -- "$cur")) } && complete -F _tpm2_policypassword tpm2_policypassword # ex: filetype=sh # bash completion for tpm2_policypcr -*- shell-script -*- _tpm2_policypcr() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -f | --pcr) _filedir return;; -l | --pcr-list) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -f -l -S --policy --pcr --pcr-list --session " \ -- "$cur")) } && complete -F _tpm2_policypcr tpm2_policypcr # ex: filetype=sh # bash completion for tpm2_policyrestart -*- shell-script -*- _tpm2_policyrestart() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -S --session " \ -- "$cur")) } && complete -F _tpm2_policyrestart tpm2_policyrestart # ex: filetype=sh # bash completion for tpm2_policysecret -*- shell-script -*- _tpm2_policysecret() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --object-context) _filedir return;; -S | --session) _filedir return;; -L | --policy) _filedir return;; -t | --expiration) _filedir return;; -x | --nonce-tpm) _filedir return;; -q | --qualification) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -S -L -t -x -q --object-context --session --policy --expiration --nonce-tpm --qualification --ticket --timeout --cphash " \ -- "$cur")) } && complete -F _tpm2_policysecret tpm2_policysecret # ex: filetype=sh # bash completion for tpm2_policysigned -*- shell-script -*- _tpm2_policysigned() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -c | --key-context) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -t | --expiration) _filedir return;; -q | --qualification) _filedir return;; -x | --nonce-tpm) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S -c -g -s -f -t -q -x --policy --session --key-context --hash-algorithm --signature --format --expiration --qualification --nonce-tpm --ticket --timeout " \ -- "$cur")) } && complete -F _tpm2_policysigned tpm2_policysigned # ex: filetype=sh # bash completion for tpm2_policytemplate -*- shell-script -*- _tpm2_policytemplate() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S --policy --session " \ -- "$cur")) } && complete -F _tpm2_policytemplate tpm2_policytemplate # ex: filetype=sh # bash completion for tpm2_policyticket -*- shell-script -*- _tpm2_policyticket() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -L | --policy) _filedir return;; -S | --session) _filedir return;; -n | --name) _filedir return;; -q | --qualification) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -L -S -n -q --policy --session --name --qualification --ticket --timeout " \ -- "$cur")) } && complete -F _tpm2_policyticket tpm2_policyticket # ex: filetype=sh # bash completion for tpm2_print -*- shell-script -*- _tpm2_print() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -t | --type) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -t --type " \ -- "$cur")) } && complete -F _tpm2_print tpm2_print # ex: filetype=sh # bash completion for tpm2_quote -*- shell-script -*- _tpm2_quote() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local pcr_format_methods=(values serialized) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -l | --pcr-list) _filedir return;; -F | --pcrs_format) COMPREPLY=($(compgen -W "${pcr_format_methods[*]}" -- "$cur")) return;; -m | --message) _filedir return;; -s | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; -o | --pcr) _filedir return;; -q | --qualification) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti -F --pcrs_format \ -c -p -l -m -s -f -o -q -g --key-context --auth --pcr-list --message --signature --format --pcr --qualification --hash-algorithm --cphash " \ -- "$cur")) } && complete -F _tpm2_quote tpm2_quote # ex: filetype=sh # bash completion for tpm2_rc_decode -*- shell-script -*- _tpm2_rc_decode() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_rc_decode tpm2_rc_decode # ex: filetype=sh # bash completion for tpm2_readclock -*- shell-script -*- _tpm2_readclock() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_readclock tpm2_readclock # ex: filetype=sh # bash completion for tpm2_readpublic -*- shell-script -*- _tpm2_readpublic() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --object-context) _filedir return;; -n | --name) _filedir return;; -o | --output) _filedir return;; -t | --serialized-handle) _filedir return;; -q | --qualified-name) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -n -o -t -q --object-context --name --output --serialized-handle --qualified-name " \ -- "$cur")) } && complete -F _tpm2_readpublic tpm2_readpublic # ex: filetype=sh # bash completion for tpm2_rsadecrypt -*- shell-script -*- _tpm2_rsadecrypt() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -o | --output) _filedir return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -l | --label) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -o -s -l --key-context --auth --output --scheme --label --cphash " \ -- "$cur")) } && complete -F _tpm2_rsadecrypt tpm2_rsadecrypt # ex: filetype=sh # bash completion for tpm2_rsaencrypt -*- shell-script -*- _tpm2_rsaencrypt() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -o | --output) _filedir return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -l | --label) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -o -s -l --key-context --output --scheme --label " \ -- "$cur")) } && complete -F _tpm2_rsaencrypt tpm2_rsaencrypt # ex: filetype=sh # bash completion for tpm2_selftest -*- shell-script -*- _tpm2_selftest() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -f | --fulltest) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -f --fulltest " \ -- "$cur")) } && complete -F _tpm2_selftest tpm2_selftest # ex: filetype=sh # bash completion for tpm2_send -*- shell-script -*- _tpm2_send() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -o --output " \ -- "$cur")) } && complete -F _tpm2_send tpm2_send # ex: filetype=sh # bash completion for tpm2_setclock -*- shell-script -*- _tpm2_setclock() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --hierarchy) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p --hierarchy --auth --cphash " \ -- "$cur")) } && complete -F _tpm2_setclock tpm2_setclock # ex: filetype=sh # bash completion for tpm2_setcommandauditstatus -*- shell-script -*- _tpm2_setcommandauditstatus() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --hierarchy-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -c | --clear-list) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -c -g --hierarchy --hierarchy-auth --clear-list --hash-algorithm " \ -- "$cur")) } && complete -F _tpm2_setcommandauditstatus tpm2_setcommandauditstatus # ex: filetype=sh # bash completion for tpm2_setprimarypolicy -*- shell-script -*- _tpm2_setprimarypolicy() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -C | --hierarchy) _filedir return;; -P | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -L | --policy) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -C -P -L -g --hierarchy --auth --policy --hash-algorithm --cphash " \ -- "$cur")) } && complete -F _tpm2_setprimarypolicy tpm2_setprimarypolicy # ex: filetype=sh # bash completion for tpm2_shutdown -*- shell-script -*- _tpm2_shutdown() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --clear) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c --clear " \ -- "$cur")) } && complete -F _tpm2_shutdown tpm2_shutdown # ex: filetype=sh # bash completion for tpm2_sign -*- shell-script -*- _tpm2_sign() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -d | --digest) _filedir return;; -t | --ticket) _filedir return;; -o | --signature) _filedir return;; -f | --format) COMPREPLY=($(compgen -W "${format_methods[*]}" -- "$cur")) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -g -s -d -t -o -f --key-context --auth --hash-algorithm --scheme --digest --ticket --signature --format --cphash " \ -- "$cur")) } && complete -F _tpm2_sign tpm2_sign # ex: filetype=sh # bash completion for tpm2_startauthsession -*- shell-script -*- _tpm2_startauthsession() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -c | --key-context) _filedir return;; -S | --session) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -g -c -S --hash-algorithm --key-context --session --policy --audit " \ -- "$cur")) } && complete -F _tpm2_startauthsession tpm2_startauthsession # ex: filetype=sh # bash completion for tpm2_startup -*- shell-script -*- _tpm2_startup() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --clear) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c --clear " \ -- "$cur")) } && complete -F _tpm2_startup tpm2_startup # ex: filetype=sh # bash completion for tpm2_stirrandom -*- shell-script -*- _tpm2_stirrandom() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_stirrandom tpm2_stirrandom # ex: filetype=sh # bash completion for tpm2_testparms -*- shell-script -*- _tpm2_testparms() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ " \ -- "$cur")) } && complete -F _tpm2_testparms tpm2_testparms # ex: filetype=sh # bash completion for tpm2_unseal -*- shell-script -*- _tpm2_unseal() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --object-context) _filedir return;; -p | --auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -o | --output) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -o --object-context --auth --output --cphash " \ -- "$cur")) } && complete -F _tpm2_unseal tpm2_unseal # ex: filetype=sh # bash completion for tpm2_verifysignature -*- shell-script -*- _tpm2_verifysignature() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -g | --hash-algorithm) COMPREPLY=($(compgen -W "${hash_methods[*]}" -- "$cur")) return;; -m | --message) _filedir return;; -d | --digest) _filedir return;; -s | --signature) _filedir return;; -f | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -t | --ticket) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -g -m -d -s -f -t --key-context --hash-algorithm --message --digest --signature --scheme --ticket --format " \ -- "$cur")) } && complete -F _tpm2_verifysignature tpm2_verifysignature # ex: filetype=sh # bash completion for tpm2_zgen2phase -*- shell-script -*- _tpm2_zgen2phase() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \ sensitivedataorigin userwithauth adminwithpolicy noda \ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \ policydelete writelocked writeall writedefine write_stclear \ globallock ppread ownerread authread policyread no_da orderly \ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case $prev in -h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -T | --tcti) COMPREPLY=( $(compgen -W "tabrmd mssim device none" -- "$cur") ) return;; -c | --key-context) _filedir return;; -p | --key-auth) COMPREPLY=($(compgen -W "${auth_methods[*]}" -- "$cur")) return;; -s | --scheme) COMPREPLY=($(compgen -W "${signing_scheme[*]}" -- "$cur")) return;; -t | --counter) _filedir return;; esac COMPREPLY=($(compgen -W "-h --help -v --version -V --verbose -Q --quiet \ -Z --enable-erata -T --tcti \ -c -p -s -t --key-context --key-auth --scheme --counter --static --ephemeral --output --output " \ -- "$cur")) } && complete -F _tpm2_zgen2phase tpm2_zgen2phase # ex: filetype=sh _tpm2() { local cur prev words cword split _init_completion -s || return if ((cword == 1)); then COMPREPLY=($(compgen -W "activatecredential certify certifyX509certutil certifycreation changeauth changeeps changepps checkquote clear clearcontrol clockrateadjust commit create createak createek createpolicy createprimary dictionarylockout duplicate ecdhkeygen ecdhzgen ecephemeral encryptdecrypt eventlog evictcontrol flushcontext getcap getcommandauditdigest geteccparameters getekcertificate getrandom getsessionauditdigest gettestresult gettime hash hierarchycontrol hmac import incrementalselftest load loadexternal makecredential nvcertify nvdefine nvextend nvincrement nvread nvreadlock nvreadpublic nvsetbits nvundefine nvwrite nvwritelock pcrallocate pcrevent pcrextend pcrread pcrreset policyauthorize policyauthorizenv policyauthvalue policycommandcode policycountertimer policycphash policyduplicationselect policylocality policynamehash policynv policynvwritten policyor policypassword policypcr policyrestart policysecret policysigned policytemplate policyticket print quote rc_decode readclock readpublic rsadecrypt rsaencrypt selftest send setclock setcommandauditstatus setprimarypolicy shutdown sign startauthsession startup stirrandom testparms unseal verifysignature zgen2phase " -- "$cur")) else tpmcommand=_tpm2_$prev type $tpmcommand &>/dev/null && $tpmcommand if [ $? == 1 ];then COMPREPLY=($(compgen -W ${words[1]} -- "$cur")) fi fi } && complete -F _tpm2 tpm2 tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2000066400000000000000000000021171412464516500222760ustar00rootroot00000000000000# bash completion for tss2 -*- shell-script -*- _tss2() { local cur prev words cword split _init_completion -s || return local commands command commands='decrypt encrypt list changeauth delete import getinfo createkey createseal exportkey getcertificate getplatformcertificates gettpmblobs setcertificate getappdata setappdata sign verifysignature verifyquote createnv nvextend nvincrement nvread nvsetbits nvwrite getdescription setdescription pcrextend quote pcrread authorizepolicy exportpolicy provision getrandom unseal writeauthorizenv' if ((cword == 1)); then COMPREPLY=($(compgen -W "$commands" -- "$cur")) else command=${words[1]} case $prev in -!(-*) | getrandom) _tss2_getrandom return;; -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; *) COMPREPLY=( $(compgen -W "--help" -- "$cur") ) return;; esac fi } && complete -F _tss2 tss2tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_authorizepolicy000066400000000000000000000014141412464516500256070ustar00rootroot00000000000000# bash completion for tss2_authorizepolicy -*- shell-script -*- _tss2_authorizepolicy() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[r] | --policyRef) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[Pp] | --policyPath | --keyPath ) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --policyPath= -P --keyPath= -p --policyRef= -r" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_authorizepolicy tss2_authorizepolicy # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_changeauth000066400000000000000000000011521412464516500244630ustar00rootroot00000000000000# bash completion for tss2_changeauth -*- shell-script -*- _tss2_changeauth() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[ap] | --authValue | --entityPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -a --authValue= -p --entityPath=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_changeauth tss2_changeauth # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_createkey000066400000000000000000000012311412464516500243260ustar00rootroot00000000000000# bash completion for tss2_createkey -*- shell-script -*- _tss2_createkey() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[ptPa] | --path | --type | --policyPath | --authValue) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -p --path= -t --type= -P --policyPath= -a --authValue=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_createkey tss2_createkey # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_createnv000066400000000000000000000012351412464516500241650ustar00rootroot00000000000000# bash completion for tss2_createnv -*- shell-script -*- _tss2_createnv() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[stpPa] | --size | --type | --path | --policyPath | --authValue) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -P --policyPath= -p --path= -s --size= -t --type= -a --authValue=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_createnv tss2_createnv # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_createseal000066400000000000000000000014711412464516500244700ustar00rootroot00000000000000# bash completion for tss2_createseal -*- shell-script -*- _tss2_createseal() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[i] | --data) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[ptPas] | --path | --type | --policyPath | --authValue | --size) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --authValue= -a --path= -p --policyPath= -P --type= -t --data= -i --size= -s" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_createseal tss2_createseal # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_decrypt000066400000000000000000000013501412464516500240260ustar00rootroot00000000000000# bash completion for tss2_decrypt -*- shell-script -*- _tss2_decrypt() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[io] | --cipherText | --plainText) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)p | --keyPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f -i --cipherText= --plainText= -o --keyPath= -p" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_decrypt tss2_decrypt # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_delete000066400000000000000000000010551412464516500236200ustar00rootroot00000000000000# bash completion for tss2_delete -*- shell-script -*- _tss2_delete() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)p | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -p --path=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_delete tss2_delete # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_encrypt000066400000000000000000000014021412464516500240360ustar00rootroot00000000000000# bash completion for tss2_encrypt -*- shell-script -*- _tss2_encrypt() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[io] | --plainText | --cipherText) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --keyPath ) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -f --force -o --cipherText= -p --keyPath= -i --plainText=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_encrypt tss2_encrypt # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_exportkey000066400000000000000000000015041412464516500244070ustar00rootroot00000000000000# bash completion for tss2_exportkey -*- shell-script -*- _tss2_exportkey() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[o] | --exportedData ) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[pe] | --pathOfKeyToDuplicate | --pathToPublicKeyOfNewParent) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --exportedData= -o --force -f --pathOfKeyToDuplicate= -p --pathToPublicKeyOfNewParent= -e" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_exportkey tss2_exportkey # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_exportpolicy000066400000000000000000000013611412464516500251170ustar00rootroot00000000000000# bash completion for tss2_exportpolicy -*- shell-script -*- _tss2_exportpolicy() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[o] | --jsonPolicy ) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --jsonPolicy= -o --path= -p --force -f" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_exportpolicy tss2_exportpolicy # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getappdata000066400000000000000000000013301412464516500244640ustar00rootroot00000000000000# bash completion for tss2_getappdata -*- shell-script -*- _tss2_getappdata() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[o] | --appData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f -p --path= --appData= -o" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getappdata tss2_getappdata # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getcertificate000066400000000000000000000013621412464516500253410ustar00rootroot00000000000000# bash completion for tss2_getcertificate -*- shell-script -*- _tss2_getcertificate() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[o] | --x509certData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f -p --path= --x509certData= -o" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getcertificate tss2_getcertificate # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getdescription000066400000000000000000000013501412464516500253770ustar00rootroot00000000000000# bash completion for tss2_getdescription -*- shell-script -*- _tss2_getdescription() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[o] | --description) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -f --force --path= -p --description= -o " -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getdescription tss2_getdescription # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getinfo000066400000000000000000000012201412464516500240030ustar00rootroot00000000000000# bash completion for tss2_getinfo -*- shell-script -*- _tss2_getinfo() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)o | --info) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --info= -o" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getinfo tss2_getinfo # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getplatformcertificates000066400000000000000000000013301412464516500272640ustar00rootroot00000000000000# bash completion for tss2_getplatformcertificates -*- shell-script -*- _tss2_getplatformcertificates() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)o | --certificates) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --certificates= -o" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getplatformcertificates tss2_getplatformcertificates # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_getrandom000066400000000000000000000013361412464516500243400ustar00rootroot00000000000000# bash completion for tss2_getrandom -*- shell-script -*- _tss2_getrandom() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)o | --data) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)n | --numBytes) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --hex --version --force -f --numBytes= -n --data= -o " -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_getrandom tss2_getrandom # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_gettpmblobs000066400000000000000000000014431412464516500247010ustar00rootroot00000000000000# bash completion for tss2_gettpmblobs -*- shell-script -*- _tss2_gettpmblobs() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --path ) return;; -!(-*)[url] | --tpm2bPublic | --tpm2bPrivate | --policy) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --path= -p --tpm2bPublic= -u --tpm2bPrivate= -r --policy= -l" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_gettpmblobs tss2_gettpmblobs # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_import000066400000000000000000000013101412464516500236620ustar00rootroot00000000000000# bash completion for tss2_import -*- shell-script -*- _tss2_import() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --path) return;; -!(-*)[i] | --importData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --importData= -i --path= -p" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_import tss2_import # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_list000066400000000000000000000013271412464516500233330ustar00rootroot00000000000000# bash completion for tss2_list -*- shell-script -*- _tss2_list() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --searchPath) return;; -!(-*)[o] | --pathList) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --pathList= -o --searchPath= -p" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_list tss2_list # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_nvextend000066400000000000000000000013511412464516500242100ustar00rootroot00000000000000# bash completion for tss2_nvextend -*- shell-script -*- _tss2_nvextend() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[il] | --data | --logData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[p] | --nvPath ) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --data= -i --nvPath= -p --logData= -l" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_nvextend tss2_nvextend # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_nvincrement000066400000000000000000000011061412464516500247030ustar00rootroot00000000000000# bash completion for tss2_nvincremend -*- shell-script -*- _tss2_nvincrement() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)p | --nvPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --nvPath= -p" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_nvincrement tss2_nvincrement # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_nvread000066400000000000000000000013541412464516500236370ustar00rootroot00000000000000# bash completion for tss2_nvread -*- shell-script -*- _tss2_nvread() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --nvPath) return;; -!(-*)[ol] | --data | --logData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --nvPath= -p --data= -o --logData= -l" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_nvread tss2_nvread # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_nvsetbits000066400000000000000000000011331412464516500243740ustar00rootroot00000000000000# bash completion for tss2_nvsetbits -*- shell-script -*- _tss2_nvsetbits() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[ip] | --bitmap | --nvPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -i --bitmap= -p --nvPath=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_nvsetbits tss2_nvsetbits # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_nvwrite000066400000000000000000000013111412464516500240470ustar00rootroot00000000000000# bash completion for tss2_nvwrite -*- shell-script -*- _tss2_nvwrite() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --nvPath) return;; -!(-*)[i] | --data) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --nvPath= -p --data= -i" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_nvwrite tss2_nvwrite # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_pcrextend000066400000000000000000000013441412464516500243530ustar00rootroot00000000000000# bash completion for tss2_pcrextend -*- shell-script -*- _tss2_pcrextend() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[x] | --pcr) return;; -!(-*)[il] | --data | --logData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -x --pcr= -i --data= -l --logData=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_pcrextend tss2_pcrextend # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_pcrread000066400000000000000000000013621412464516500237770ustar00rootroot00000000000000# bash completion for tss2_pcrread -*- shell-script -*- _tss2_pcrread() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[x] | --pcrIndex) return;; -!(-*)[ol] | --pcrValue | --pcrLog) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -o --pcrValue= -x --pcrIndex= --force -f -l --pcrLog=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_pcrread tss2_pcrread # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_provision000066400000000000000000000012361412464516500244070ustar00rootroot00000000000000# bash completion for tss2_provision -*- shell-script -*- _tss2_provision() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[ESL] | --authValueEh | --authValueSh | --authValueLockout ) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -E -S -L --authValueEh= --authValueSh= --authValueLockout=" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_provision tss2_provision # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_quote000066400000000000000000000015671412464516500235230ustar00rootroot00000000000000# bash completion for tss2_quote -*- shell-script -*- _tss2_quote() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[px] | --keyPath | --pcrList) return;; -!(-*)[olqQc] | --signature | --pcrLog | --quoteInfo | --qualifyingData | --certificate) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --pcrList= -x --qualifyingData= -Q --pcrLog= -l --force -f --keyPath= -p --quoteInfo= -q --signature= -o --certificate= -c " -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_quote tss2_quote # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_setappdata000066400000000000000000000013151412464516500245030ustar00rootroot00000000000000# bash completion for tss2_setappdata -*- shell-script -*- _tss2_setappdata() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[p] | --path ) return;; -!(-*)i | --appData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -p --path= --appData= -i" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_setappdata tss2_setappdata # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_setcertificate000066400000000000000000000013431412464516500253540ustar00rootroot00000000000000# bash completion for tss2_setcertificate -*- shell-script -*- _tss2_setcertificate() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)i | --x509certData) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)p | --path) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version -p --path= --x509certData= -i" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_setcertificate tss2_setcertificate # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_setdescription000066400000000000000000000011411412464516500254110ustar00rootroot00000000000000# bash completion for tss2_setdescription -*- shell-script -*- _tss2_setdescription() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[pi] | --path | --description) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --path= -p --description= -i " -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_setdescription tss2_setdescription # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_sign000066400000000000000000000015121412464516500233140ustar00rootroot00000000000000# bash completion for tss2_sign -*- shell-script -*- _tss2_sign() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[dokc] | --digest | --signature | --publicKey | --certificate) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[ps] | --keyPath | --padding) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --force -f --certificate= -c --digest= -d --keyPath= -p --publicKey= -k --signature= -o --padding= -s" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_sign tss2_sign # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_unseal000066400000000000000000000013111412464516500236400ustar00rootroot00000000000000# bash completion for tss2_unseal -*- shell-script -*- _tss2_unseal() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)o | --data) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)p | --path ) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --data= -o -f --force --path= -p" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_unseal tss2_unseal # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_verifyquote000066400000000000000000000015131412464516500247370ustar00rootroot00000000000000# bash completion for tss2_verifyquote -*- shell-script -*- _tss2_verifyquote() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[Qilq] | --qualifyingData | --signature | --pcrLog | --quoteInfo) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)[k] | --publicKeyPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --qualifyingData= -Q --pcrLog= -l --quoteInfo= -q --publicKeyPath= -k --signature= -i" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_verifyquote tss2_verifyquote # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_verifysignature000066400000000000000000000014011412464516500255770ustar00rootroot00000000000000# bash completion for tss2_verifysignature -*- shell-script -*- _tss2_verifysignature() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[di] | --digest | --signature) _filedir if [ x"$cur" = x ]; then COMPREPLY+=( '-' ); fi return;; -!(-*)p | --keyPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --digest= -d --keyPath= -p --signature= -i" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_verifysignature tss2_verifysignature # ex: filetype=sh tpm2-tools-5.2/dist/bash-completion/tpm2-tools/tss2_writeauthorizenv000066400000000000000000000012001412464516500257770ustar00rootroot00000000000000# bash completion for tss2_writeauthorizenv -*- shell-script -*- _tss2_writeauthorizenv() { local cur prev words cword split _init_completion -s || return case $prev in -!(-*)h | --help) COMPREPLY=( $(compgen -W "man no-man" -- "$cur") ) return;; -!(-*)[pP] | --nvPath | --policyPath) return;; esac $split && return COMPREPLY=( $(compgen -W "-h --help -v --version --nvPath= -p -policyPath= -P" -- "$cur") ) [[ $COMPREPLY == *= ]] && compopt -o nospace } && complete -F _tss2_writeauthorizenv tss2_writeauthorizenv # ex: filetype=sh tpm2-tools-5.2/doc/000077500000000000000000000000001412464516500141555ustar00rootroot00000000000000tpm2-tools-5.2/doc/AUTHORS.md000066400000000000000000000012151412464516500156230ustar00rootroot00000000000000## Authors The *tpm2-tools* project was created by Gang Wei at Intel Inc. A list of **MUCH APPRECIATED** contributors follows. If you are not on this list but feel you should be, please contact the current maintainer(s). * atomsoftwarestudios * Benyu Xu * DamienMolina * Dandan Tu * Dewei Zhang * Erez Geva * Gang "Jimmy" Wei * Imran Desai * jethrogb * Philip Tricca * Javier Martinez Canillas tpm2-tools-5.2/doc/CHANGELOG.md000066400000000000000000002057251412464516500160010ustar00rootroot00000000000000## Changelog ### 5.2 2021-09-28 ### 5.2-rc0 2021-09-01 * tpm2_nvextend: * Added option -n, --name to specify the name of the nvindex in hex bytes. This is used when cpHash ought to be calculated without dispatching the TPM2_NV_Extend command to the TPM. * tpm2_nvread: * Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * Added option **\-n**, **\--name** to specify the name of the nvindex in hex bytes. This is used when cpHash ought to be calculated without dispatching the TPM2_NVRead command to the TPM. * Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_nvsetbits: * Added option **\--rphash**=_FILE_ to specify file path to record the hash of the response parameters. This is commonly termed as rpHash. * Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * Added option **\-n**, **\--name** to specify the name of the nvindex in hex bytes. This is used when cpHash ought to be calculated without dispatching the TPM2_NV_SetBits command to the TPM. * tpm2_createprimary: * Support public-key output at creation time in various public-key formats. * tpm2_create: * Support public-key output at creation time in various public-key formats. * tpm2_print: * Support outputing public key in various public key formats over the default YAML output. Supports taking `-u` output from `tpm2_create` and converting it to a PEM or DER file format. * tpm2_import: * Add support for importing keys with sealed-data-blobs. * tpm2_rsaencrypt, tpm2_rsadecrypt: * Add support for specifying the hash algorithm with oaep. * tpm2_pcrread, tpm2_quote: * Add option **-F**, **\--pcrs_format** to specify PCR format selection for the binary blob in the PCR output file. 'values' will output a binary blob of the PCR values. 'serialized' will output a binary blob of the PCR values in the form of serialized data structure in little endian format. * tpm2_eventlog: * Add support for decoding StartupLocality. * Add support for printing the partition information. * Add support for reading eventlogs longer than 64kb including from /sys/kernel/security/tpm0/binary_bios-measurements. * tpm2_duplicate: * Add option **-L**, **\--policy** to specify an authorization policy to be associated with the duplicated object. * Added support for external key duplication without needing the TCTI. * tools: * Enhance error message on invalid passwords when sessions cannot be used. * lib/tpm2_options: * Add option to specify fake tcti which is required in cases where sapi ctx is required to be initialized for retrieving command parameters without invoking the tcti to talk to the TPM. * openssl: * Dropped support for OpenSSL < 1.1.0 * Add support for OpenSSL 3.0.0 * Support added to make the repository documentation and man pages available live on readthedocs. * Bug-fixes: * tpm2_import: Don't allow setting passwords for imported object with -p option as the tool doesn't modify the TPM2B_SENSITIVE structure. Added appropriate logging to indicate using **tpm2_changeauth** after import. * lib/tpm2_util.c: The function to calculate pHash algorithm returned error when input session is a password session and the only session in the command. * lib/tpm2_alg_util.c: Fix an error where oaep was parsed under ECC. * tpm2_sign: Fix segfaults when tool does not find TPM resources (TPM or RM). * tpm2_makecredential: Fix an issue where reading input from stdin could result in unsupported data size larger than the largest digest size. * tpm2_loadexternal: Fix an issue where restricted attribute could not be set. * lib/tpm2_nv_util.h: The NV index size is dependent on different data sets read from the GetCapability structures because there is a dependency on the NV operation type: Define vs Read vs Write vs Extend. Fix a sane default in the case where GetCapability fails or fails to report the specific property/ data set. This is especially true because some properties are TPM implementation dependent. * tpm2_createpolicy: Fix an issue where tool exited silently without reporting an error if wrong pcr string is specified. * lib/tpm2_alg_util: add error message on public init to prevent tools from dying silently, add an error message. * tpm2_import: fix an issue where an imported hmac object scheme was NULL. While allowed, it was inconsistent with other tools like tpm2_create which set the scheme as hmac->sha256 when generating a keyedhash object. ### 5.1.1 2021-06-21 * tpm2_import: fix fixed AES key CVE-2021-3565 - tpm2_import used a fixed AES key for the inner wrapper, which means that a MITM attack would be able to unwrap the imported key. To fix this, ensure the key size is 16 bytes or bigger and use OpenSSL to generate a secure random AES key. ### 5.1 2021-05-24 * Build - Dependency-update: Minimum tpm2-tss version dependency bumped to 3.1.0 - Dependency-update: Minimum tpm2-abrmd version dependency bumped to 2.4.0 - tpm2_eventlog: Fix build errors on 64 bit arm systems. - tpm2_checkquote: Fix build on 32b little-endian platforms. - Fixes builds on CentOS 7 which notably has an ancient version of GCC: 4.8.5 and an older version of OSSL, 1.0.2 - Configure handles searching for python executable more gracefully, thus just having python3, will work. - Moved to GitHub Actions for CI testing. - Added fedora-32 to CI testing configurations and related fixes. - FreeBSD testing is bumped up to version 12.2 - Fix compiler and packaging warnings for OpenSuse builds. - configure: make build gnu99. - configure: make -Wbool-compare non fatal. - configure: only use -Werror for non-release builds * tss2: - Support in tools for PolicyRef inclusion in policy search per latest TSS. - Support to use TPM objects protected by a policy with PolicySigned. - Enable backward compatibility to old Fapi callback API. - Fix PCR selection for tss2 quote. - Support policy signed policies by implementing Fapi_SetSignCB. * Command/ response parameter support for auditing and pHash policies: - lib/tpm2_util.c: Add method to determine hashing alg for cp/rphash - Add support to calculate rphash for tpm2_create, tpm2_activatecredential, tpm2_certify, tpm2_certifycreation, tpm2_changeauth, tpm2_changeeps, tpm2_changepps, tpm2_nvdefine, tpm2_nvextend, tpm2_unseal - Add support to calculate cphash for tpm2_changeeps, tpm2_changepps. * Session-support: - tpm2_sessionconfig: Add tool to display and configure session attributes. - tpm2_getrandom: Fix— session input was hardcoded for audit-only - tpm2_startauthsession: Add option to specify the bind object and its authorization value. - tpm2_startauthsession: support for bounded-only session. - tpm2_startauthsession: support for salted-only session. - tpm2_startauthsession: add option to specify an hmac session type. - Add support for specifying non-authorization sessions for audit and parameter encryption for tpm2_getrandom, tpm2_create, tpm2_nvextend, tpm2_nvdefine, tpm2_unseal, tpm2_activatecredential, tpm2_certify, tpm2_certifycreation, tpm2_changeauth, tpm2_changeeps, tpm2_changepps. * tpm2_eventlog: - Support for event type: EV_IPL extensively used by the Shim and Grub. - Support for event type: EV_EFI_GPT_EVENT to parse. UEFI_PARTITION_TABLE_HEADER and UEFI_PARTITION_ENTRY. - Support for event type: EFI_SIGNATURE_LIST, which contains one or more EFI_SIGNATURE_DATA. - Support for event type EV_EFI_VARIABLE_AUTHORITY. - Parse UEFI_PLATFORM_FIRMWARE_BLOB structure that the CRTM MUST put into the Event Log entry TCG_PCR_EVENT2.event field for event types EV_POST_CODE, EV_S_CRTM_CONTENTS, and EV_EFI_PLATFORM_FIRMWARE_BLOB. - Parse secureboot variable to indicate enable as 'Yes'. - Parse BootOrder variable to a more readable format. - Parse Boot variables per EFI_LOAD_OPTION described in more details in UEFI Spec Section 3.1.3 - Parse Device-path in a readable format using the efivar library. - Support for logs longer than 64 kilobytes. - Perform verification for event types where digest can be verified from their event payload. - Better support for multiline strings. - Fix handling of event log EV_POST_CODE data where field is empty and len is specified. * scripts/utils: Add a utility to read the cert chain of embedded CA. * tpm2_getekcertificate: Fix tool failing to return error/non-zero for HTTP 404. * tpm2_nvdefine: allow setting hash algorithm by command line parameter for NV indices set in extend mode. * tpm2_duplicate, tpm2_import: support duplicating non-TPM keys to a remote TPM without first requiring them to be loaded to a local TPM. * tpm2_dictionarylockout: Fix issue where setting value for one parameter caused to reset the others. * tpm2_getpolicydigest: Add new tool to enable TPM2_CC_PolicyGetDigest. * Fix segfault where optind > argc. * tools/tpm2_checkquote: fix missing initializer * tpm2_convert: fix EVP_EncodeUpdate usage for OSSL < 1.1.0 * openssl: fix EVP_ENCODE_CTX_(new|free) * test: Add support for swTPM simulator to the testing framework and make it the default if mssim isn't available. * tpm2_unseal: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_nvextend: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_nvdefine: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_changepps: - Added option **\--cphash**=_FILE_ to specify ile path to record the hash of the command parameters. This is commonly termed as cpHash. - Added option **\--rphash**=_FILE_ to specify ile path to record the hash - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_changeeps: - Added option **\--cphash**=_FILE_ to specify ile path to record the hash of the command parameters. This is commonly termed as cpHash. - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_changeauth: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_certifycreation: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_certify: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_activatecredential: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_create: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_unseal: - Added option **-S**, **--session** to specify auxiliary sessions for audit and encryption. * tpm2_nvdefine: - Added option **-S**, **--session** to specify auxiliary sessions for audit and encryption. * tpm2_nvextend: - Added option **-S**, **--session** to specify auxilary sessions for audit and encryption. ### 5.1-rc1 2021-05-19 * scripts/utils: Add a utility to read the cert chain of embedded CA * .ci/download-deps.sh: Bump tpm2-tss version to 3.1.0 * build: only use -Werror for non-release builds ### 5.1-rc0 2021-04-20 * Build - Dependency-update: Minimum tpm2-tss version dependency bumped to 3.0.3 - Dependency-update: Minimum tpm2-abrmd version dependency bumped to 2.4.0 - tpm2_eventlog: Fix build errors on 64 bit arm systems. - tpm2_checkquote: Fix build on 32b little-endian platforms. - Fixes builds on CentOS 7 which notably has an ancient version of GCC: 4.8.5 and an older version of OSSL, 1.0.2 - Configure handles searching for python executable more gracefully, thus just having python3, will work. - Moved to GitHub Actions for CI testing. - Added fedora-32 to CI testing configurations and related fixes. - FreeBSD testing is bumped up to version 12.2 - Fix compiler and packaging warnings for OpenSuse builds. - configure: make build gnu99. - configure: make -Wbool-compare non fatal. * tss2: - Support in tools for PolicyRef inclusion in policy search per latest TSS. - Support to use TPM objects protected by a policy with PolicySigned. - Enable backward compatibility to old Fapi callback API. - Fix PCR selection for tss2 quote. - Support policy signed policies by implementing Fapi_SetSignCB. * Command/ response parameter support for auditing and pHash policies: - lib/tpm2_util.c: Add method to determine hashing alg for cp/rphash - Add support to calculate rphash for tpm2_create, tpm2_activatecredential, tpm2_certify, tpm2_certifycreation, tpm2_changeauth, tpm2_changeeps, tpm2_changepps, tpm2_nvdefine, tpm2_nvextend, tpm2_unseal - Add support to calculate cphash for tpm2_changeeps, tpm2_changepps. * Session-support: - tpm2_sessionconfig: Add tool to display and configure session attributes. - tpm2_getrandom: Fix— session input was hardcoded for audit-only - tpm2_startauthsession: Add option to specify the bind object and its authorization value. - tpm2_startauthsession: support for bounded-only session. - tpm2_startauthsession: support for salted-only session. - tpm2_startauthsession: add option to specify an hmac session type. - Add support for specifying non-authorization sessions for audit and parameter encryption for tpm2_getrandom, tpm2_create, tpm2_nvextend, tpm2_nvdefine, tpm2_unseal, tpm2_activatecredential, tpm2_certify, tpm2_certifycreation, tpm2_changeauth, tpm2_changeeps, tpm2_changepps. * tpm2_eventlog: - Support for event type: EV_IPL extensively used by the Shim and Grub. - Support for event type: EV_EFI_GPT_EVENT to parse. UEFI_PARTITION_TABLE_HEADER and UEFI_PARTITION_ENTRY. - Support for event type: EFI_SIGNATURE_LIST, which contains one or more EFI_SIGNATURE_DATA. - Support for event type EV_EFI_VARIABLE_AUTHORITY. - Parse UEFI_PLATFORM_FIRMWARE_BLOB structure that the CRTM MUST put into the Event Log entry TCG_PCR_EVENT2.event field for event types EV_POST_CODE, EV_S_CRTM_CONTENTS, and EV_EFI_PLATFORM_FIRMWARE_BLOB. - Parse secureboot variable to indicate enable as 'Yes'. - Parse BootOrder variable to a more readable format. - Parse Boot variables per EFI_LOAD_OPTION described in more details in UEFI Spec Section 3.1.3 - Parse Device-path in a readable format using the efivar library. - Support for logs longer than 64 kilobytes. - Perform verification for event types where digest can be verified from their event payload. - Better support for multiline strings. - Fix handling of event log EV_POST_CODE data where field is empty and len is specified. * tpm2_getekcertificate: Fix tool failing to return error/non-zero for HTTP 404. * tpm2_nvdefine: allow setting hash algorithm by command line parameter for NV indices set in extend mode. * tpm2_duplicate, tpm2_import: support duplicating non-TPM keys to a remote TPM without first requiring them to be loaded to a local TPM. * tpm2_dictionarylockout: Fix issue where setting value for one parameter caused to reset the others. * tpm2_getpolicydigest: Add new tool to enable TPM2_CC_PolicyGetDigest. * Fix segfault where optind > argc. * tools/tpm2_checkquote: fix missing initializer * tpm2_convert: fix EVP_EncodeUpdate usage for OSSL < 1.1.0 * openssl: fix EVP_ENCODE_CTX_(new|free) * test: Add support for swTPM simulator to the testing framework and make it the default if mssim isn't available. * tpm2_unseal: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_nvextend: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_nvdefine: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_changepps: - Added option **\--cphash**=_FILE_ to specify ile path to record the hash of the command parameters. This is commonly termed as cpHash. - Added option **\--rphash**=_FILE_ to specify ile path to record the hash - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_changeeps: - Added option **\--cphash**=_FILE_ to specify ile path to record the hash of the command parameters. This is commonly termed as cpHash. - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_changeauth: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_certifycreation: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_certify: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_activatecredential: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. - Added option **-S**, **\--session** to specify to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * tpm2_create: - Added option **\--rphash**=_FILE_ to specify ile path to record the hash of the response parameters. This is commonly termed as rpHash. * tpm2_unseal: - Added option **-S**, **--session** to specify auxiliary sessions for audit and encryption. * tpm2_nvdefine: - Added option **-S**, **--session** to specify auxiliary sessions for audit and encryption. * tpm2_nvextend: - Added option **-S**, **--session** to specify auxilary sessions for audit and encryption. ### 5.0 - 2020-11-16 #### Non Backwards Compatible Changes * Default hash algorithm is now sha256. Prior versions claimed sha1, but were inconsistent in choice. Best practice is to specify the hash algorithm to avoid suprises. * tpm2_tools and tss2_tools are now a busybox style commandlet. Ie tpm2\_getrandom becomes tpm2 getrandom. make install will install symlinks to the old tool names and the tpm2 commandlet will interogate argv[0] for the command to run. This will provide backwards compatibility if they are installed. If you wish to use the old names not installed system wide, set DESTDIR during install to a seperate path and set the proper directory on PATH. * tpm2\_eventlog's output changed to be YAML compliant. The output before was intended to be YAML compliant but was never properly checked and tested. * umask set to 0117 for all tools. * tpm2\_getekcertificate now outputs the INTC EK certificates in PEM format by default. In order to output the URL safe variant of base64 encoded output of the INTC EK certificate use the added option **--raw**. #### Dependency update * Update tpm2-tss dependency version to [3.0.1](https://github.com/tpm2-software/tpm2-tss/releases/tag/3.0.1) * Update tpm2-abrmd dependency version to [2.3.3](https://github.com/tpm2-software/tpm2-abrmd/releases/tag/2.3.3) #### New tools and features * tpm2\_zgen2phase: - Add new tool to support command TPM2\_CC\_ZGen\_2Phase. * tpm2\_ecdhzgen: - Add new tool to support command TPM2\_CC\_ECDH\_ZGen. * tpm2\_ecdhkeygen: - Add new tool to support command TPM2\_CC\_ECDH\_KeyGen. * tpm2\_commit: - Add new tool to support command TPM2\_CC\_Commit. * tpm2\_ecephemeral: - Add new tool to support command TPM2\_CC\_EC\_Ephemeral. * tpm2\_geteccparameters: - Add new tool to support command TPM2\_CC\_ECC\_Parameters. * tpm2\_setcommandauditstatus: - Added new tool to support command TPM2\_CC\_SetCommandCodeAuditStatus. * tpm2\_getcommandauditstatus: - Added new tool to support command TPM2\_CC\_GetCommandAuditDigest. * tpm2\_getsessionauditdigest: - Added new tool to support command TPM2\_CC\_GetSessionAuditDigest. * tpm2\_certifyX509certutil: - Added new tool for creating partial x509 certrificates required to support the TPM2\_CC\_CertifyX509 command. * tpm2\_policysigned: - Added option **\--cphash-input** to specify the command parameter hash (cpHashA), enforcing the TPM command to be authorized as well as its handle and parameter values. * tpm2\_createprimary: - Added option to specify the unique data from the stdin by adding provision for specifying the option value for unique file as **-**. * tpm2\_startauthsession: - Added new feature/option **\--audit-session** to start an HMAC session to be used as an audit session. * tpm2\_getrandom: - Added new feature/option **-S**, **\--session** to specify a HMAC session to be used as an audit session. This adds support for auditing the command using an audit session. - Added new feature/option **\--rphash** to specify file path to record the hash of the response parameters. This is commonly termed as rpHash. - Added new feature/option **\--cphash** to specify a file path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: In absence of **\--rphash** option, when this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * tpm2_getcap: - tpm2_getcap was missing raw on a property TPM2_PT_REVISION, and it should always be specified. * tpm2_sign: - Add option **--commit-index** to specify the commit index to use when performing an ECDAA signature. - Add support for ECDAA signature. * tpm2_getekcertificate: - Add option **--raw** to output EK certificate in URL safe variant base64 encoded format. By default it outputs a PEM formatted certificate. - The tool can now output INTC and non INTC EK certificates from NV indices specified by the TCG EK profile specification. * tpm2_activatecredential: - The secret data input can now be specified as stdin with **-s** option. - The public key used for encryption can be specified as **-u** to make it similar to rest of the tools specifying a public key. The old **-e** option is retained for backwards compatibility. - Add option to specify the key algorithm when the input public key is in PEM format using the new option **-G**, **--key-algorithm**. Can specify either RSA/ECC. When this option is used, input public key is expected to be in PEM format and the default TCG EK template is used for the key properties. * tpm2\_checkqoute: - Add EC support. - Support loading *tss* signatures. - Support loading tpm2 pcrread PCR values by specifying the PCR selection using the new option **-l**, **\--pcr-list**. - Added support for automatically detecting the signature format. With this **-F**, **\--format** option is retained for backwards compatibility but it is deprecated. * tpm2\_createak: - add option to output qualified name with new option **-q**, **\--ak-qualified-name**. * tpm2\_policypcr: - Add option for specifying cumulative hash of PCR's as an argument. * tpm2\_readpublic: - Add option to output qualified name using the new option **-q**, **\--qualified-name**. * tpm2\_print: - Support printing TPM2B\_PUBLIC data structures. - Support printing TPMT\_PUBLIC data structures. * tpm2\_send: - Add support for handling sending and receiving command and response buffer for multiple commands. * tpm2\_verifysignature: - Added support for verifying RSA-PSS signatures. * tpm2\_eventlog: - Add handling of sha1 log format. - Add fixes for eventlog output to be proper YAML. - Add support for sha384, sha512, sm3_256 PCR hash algorithms. - Add support for computing PCR values based on the events. * tpm2_tools (all): - Set stdin/stdout to non-buffering. - Added changes for FreeBSD portability. #### Bug fixes * Fix printing short options when no ascii character is used. * OpenSSL: Fix deprecated OpenSSL functions. ECC Functions with suffix GFp will become deprecated (DEPRECATED_1_2_0). * tpm2\_eventlog: output EV_POST_CODE as string not firmware blob to be compliant with TCG PC Client FPF section 2.3.4.1 and 9.4.12.3.4.1 * Fix missing handle maps for ESY3 handle breaks. See #1994. * tpm2\_rsaencrypt: fix OAEP RSA encryption failing to invalid hash selection. * tpm2\_rsadecrypt: fix OAEP RSA decryption failing to invalid hash selection. * tpm2\_sign: fix for signing failures with restricted signing keys when input data to sign is not a digest, rather the full message. The validation ticket creation process defaults to the owner hierarchy and so in order to choose other hierarchies the **tpm2\_hash** tool should be used instead. * tpm2\_print: fix segfault when **-t** option is omitted by appropriately warning of the required option. * tpm2\_nvdefine: fix for default size when size is not specified by invoking TPM2_CC_GetCapability. * Fix for an issue where the return code for unsupported algorithms was tool_rc_general instead of tool_rc_unsupported in **tpm2_create** and **tpm2_createprimary** tools. * Fix for an issue where RSA_PSS signature verification caused failures. * **tpm2_nvreadpublic**, **tpm2_kdfa**, **tpm2_checkquote**, **tpm2_quote**: Fixes for issues with interoperability of the attestation tools between big and little endian platforms. * tss2\_\*: - Fix bash-completion for tss2_pcrextend and tss2_verifysignature - Add force option to tss2_list - Make force option consistent in all fapi tools - Do not decode non-TPM errors - Enhance integration tests to test changes of optional/mandatory parameters - Add --hex parameter to tss2_getrandom - Fix autocompletion issue - Switch tss2\_\* to with-"="-style - Add size parameter to tss2_createseal - References to the cryptographic profile (fapi-profile(5)) and config file (fapi-config(5)) man pages from all relevant tss2\_\* man pages. - Fix policy branch selection menu item from 1 to 0. #### CI changes * Travis-CI - Drop Ubuntu-16.04 and add Ubuntu-20.04. - Added unit/integration test instance to verify we are not breaking tool options and or maintaining backwards compatibility with 4.X version. * Cirrus-CI: - Added support for testing on FreeBSD. #### Documentation * wiki pages have been removed and data has been migrated to tpm2-software.github.io portal's tutorial section. * Fix the problem with man and no-man help output for tools were not correctly displayed. * man: - tpm2_create: Correct max seal data size from 256 bytes to 128 bytes. - tpm2_nvread: Fix manpage example. - tpm2_nvwrite: Added missing information on how to specify the NV index as an argument. - tpm2_unseal: Add end-to-end example. - tpm2_nvincrement: Fix incorrect commands in example section. - tpm2_hmac: Fix the example section. ### 4.3.0 - 2020-08-24 * tss2_*: Fix double-free errors in commands asking for password authorization * tss2_*: Fix shorthand command -f that was falsely requiring an argument * tss2_*: Update tss2_encrypt to the new FAPI interface - The argument 'policyPath' is removed which was never read anyway * tss2_*: Remove the additional '\n' that was appended when redirecting to stdout * tss2_*: Update mandatory vs optional treatment of arguments according to latest Fapi spec * tss2_*: tss2_getinfo now retrieves the correct FAPI version from Fapi_GetInfo * tss2_*: Fix the error handling in case of multiple inputs and/or outputs from stdin/stdout * tss2_*: Fix syntax errors and update content of man pages according to latest Fapi spec * tss2_*: Add parameter types to all man page * tss2_*: tss2_setappdata now reads from file or stdin allowing to store also binary data * tss2_*: Memory leaks are fixed in cases when a returned empty non-char output value was passed to file output * tss2_pcrextend: fix extending PCR 0 * tss2_quote: fix unused TSS2_RC in LOG_ERR ### 4.2.1 - 2020-05-25 * Fix missing handle maps for ESY3 handle breaks. See #1994. * Bump ESYS minimum dependency version from 2.3.0 to 2.4.0. * Fix for loop declarations build error. ### 4.2 2020-04-08 * Fix various issues reported by static analysis tools. * Add integration test for ECC based getekcertificate. * Fix for issue #1959 where ARM builds were failing. * Add a check in autotools to add "expect" as a package dependency for fapi tools. * tpm2_createek: Drop the unused -p or --ek-auth option * tpm2_policyor: List of policy files should be specified as an argument instead of -l option. The -l option is still retained for backwards compatibility. See issue#1894. * tpm2\_eventlog: add a tool for parsing and displaying the event log. * tpm2_createek: Fix an issue where the `template` option looked for args * tpm2_hierarchycontrol: Fixed bug where tool operation failed silently * tpm2_nvdefine: Fixed an issue where text output suggested failures as passes * tpm2_certify: Add an example usage in man page * tpm2_policyor: Fix a bug where tool failed silently when no input were given * tpm2_getekcertificate: Intel (R) PTT EK cert web portal is set as default address * tpm2_alg_util.c: Fix a bug where string rsa3072 was not parsed * .ci/download-deps.sh: Change tss dependency to 2.4.0 to acquire SAPI handles for cpHash calculations * tpm2_policycphash: Add a tool to implement enhanced authorization with cpHash of a command * Add options to tools to enable cpHash outputs: tpm2_nvsetbits, tpm2_nvextend, tpm2_nvincrement, tpm2_nvread, tpm2_nvreadlock, tpm2_writelock, tpm2_nvdefine, tpm2_nvundefine, tpm2_nvcertify, tpm2_policynv, tpm2_policyauthorizenv, tpm2_policysecret, tpm2_create, tpm2_load, tpm2_activatecredential, tpm2_unseal, tpm2_changeauth, tpm2_duplicate, tpm2_import, tpm2_rsadecrypt, tpm2_certify, tpm2_certifycreation, tpm2_hierarchycontrol, tpm2_setprimarypolicy, tpm2_clearcontrol, tpm2_dictionarylockout, tpm2_evictcontrol, tpm2_setclock, tpm2_clockrateadjust, tpm2_clear, tpm2_nvwrite, tpm2_encryptdecrypt, tpm2_hmac. * tpm2_import: Fix an issue where the imported key always required to have a policy * tpm2_policysecret: Fix an issue where authorization model was fixed to password only * Feature API (FAPI) tools added. These additional set of tools implement utilities using the FAPI which was added to the tpm2-tss v2.4.4: tss2_decrypt, tss2_encrypt, tss2_list, tss2_changeauth, tss2_delete, tss2_import, tss2_getinfo, tss2_createkey, tss2_createseal, tss2_exportkey, tss2_getcertificate, tss2_getplatformcertificates, tss2_gettpmblobs, tss2_getappdata, tss2_setappdata, tss2_setcertificate, tss2_sign, tss2_verifysignature, tss2_verifyquote, tss2_createnv, tss2_nvextend, tss2_nvincrement, tss2_nvread, tss2_nvsetbits, tss2_nvwrite, tss2_getdescription, tss2_setdescription, tss2_pcrextend, tss2_quote, tss2_pcrread, tss2_authorizepolicy, tss2_exportpolicy, tss2_import, tss2_provision, tss2_getrandom, tss2_unseal, tss2_writeauthorizenv * tpm2_policycountertimer: Fix an issue where operandB array was reversed causing faulty comparisons. ### 4.1.3 - 2020-06-02 * tpm2\_create: Fix issue with userauth attribute being cleared if policy is specified. ### 4.1.2 - 2020-05-18 * Fix missing handle maps for ESY3 handle breaks. See #1994. ### 4.1.1 - 2020-01-21 * tpm2\_certify: Fix output of attestation data including size field. Now outputs just bytes. * tpm2\_certifycreation: Fix tool to match manpage where the code had the -C and -c options reversed. * tpm2\_gettime: Fix output of attestation data including size field. Now outputs just bytes. * tpm2\_nvcertify: Fix output of attestation data including size field. Now outputs just bytes. * tpm2\_nvreadpublic: add name hash output. * tpm2\_import: Support object policies when importing raw key material. * Fix overflow in pcrs.h where sizeof() was used instead of ARRAY\_LEN(). * build: - Fix compilation issue: lib/tpm2\_hash.c:17:19: note: 'left' was declared here. * man: - Fix manpage examples that have "sha" instead of "sha1" - tpm2\_shutdown manpage was missing, add it to build. - Fix manpage example for tpm2\_createak's tpm2\_evictcontrol example. ### 4.1 2019-11-25 * tpm2\_certifycreation: New tool enabling command TPM2\_CertifyCreation. * tpm2\_checkquote: - Fix YAML output bug. - \-g option for specifying hash algorithm is optional and defaults to sha256. * tpm2\_changeeps: A new tool for changing the Endorsement hierarchy primary seed. * tpm2\_changepps: A new tool for changing the Platform hierarchy primary seed. * tpm2\_clockrateadjust: Add a new tool for modifying the period on the TPM. * tpm2\_create: Add tool options for specifying output data for use in certification - \--creation-data to save the creation data - \--creation-ticket or -t to save the creation ticket - \--creation-hash or -d to save the creation hash - \--template-data for saving the template data of the key - \--outside-info or -q for specifying unique data to include in creation data. - \--pcr-list or -l Add option to specify pcr list to add to creation data. * tpm2\_createprimary: Add tool options for specifying output data for use in certification - \--creation-data to save the creation data - \--creation-ticket or -t to save the creation ticket - \--creation-hash or -d to save the creation hash - \--template-data for saving the template data of the key - \--outside-info or -q for specifying unique data to include in creation data. - \--pcr-list or -l Add option to specify pcr list to add to creation data. * tpm2\_evictcontrol: - Fix bug in automatic persistent handle selection when hierarchy is platform. - Fix bug in YAML key action where action was wrong when using ESYS\_TR. * tpm2\_getcap: clean up remanenats of -c option in manpages and tool output. * tpm2\_gettime: Add a new tool for retrieving a signed timestamp from a TPM. * tpm2\_nvcertify: Add a new tool for certifying the contents of an NV index. * tpm2\_nvdefine: - Support default set of attributes so -a is not mandatory. - Support searching for free index if an index isn't specified. * tpm2\_nvextend: Add a new tool for extending an NV index similair to a PCR. * tpm2\_nvreadpublic: - Support specifying nv index to read public data from as argument. * tpm2\_nvsetbits: Add a new tool for setting the values of PCR with type "bits". * tpm2\_nvundefine: Add support for deleting NV indices with attribute `TPMA_NV_POLICY_DELETE` set using NV Undefine Special command. * tpm2\_nvwritelock: Add a new tool for setting a write lock on an NV index or globally locking nv indices with TPMA\_NV\_GLOBALLOCK. * tpm2\_policyauthorizenv: New tool enabling signed, revocable policies. * tpm2\_policyauthvalue: New tool enabling authorization to be bound to the authorization of another object. * tpm2\_policycountertimer: Add a new tool for enabling policy bound to TPM clock or timer values. * tpm2\_policynamehash: Add a new tool for specifying policy based on object name. * tpm2\_policynv: Add a new tool for specifying policy based on NV contents. * tpm2\_nvwritten: Add a new tool for specifying policy based on whether or not an NV index was written to. * tpm2\_policysecret: Add tool options for specifying - \--expiration or -t - \--ticket - \--timeout - \--nonce-tpm or -x - \--qualification or -q * tpm2\_policysigned: New tool enabling policy command TPM2\_PolicySigned. * tpm2\_policytemplate: New tool enabling policy command TPM2\_PolicyTemplate. * tpm2\_policyticket: New tool enabling policy command TPM2\_PolicyTicket. * tpm2\_readclock: Add a new tool for reading the TPM clock. * tpm2\_setclock: Add a new tool for setting the TPM clock. * tpm2\_setprimarypolicy: New tool setting policy on hierarchies. * tpm2\_shutdown: Add a new tool for issuing a TPM shutdown command. * misc: - Support "tpmt" as a public key output format that only saves the TPMT structure. - Qualifying data or extra data in many tools can be hex array string or binary file. - Add support for specifying NV index type when specifying NV attributes. - Support added for tools to run on FreeBSD. - Skip and notify of action that man pages will not install if the package pandoc is missing. - Fix precedence issue with bitwise operator order int tpm2_getcap - travis: bump abrmd version 2.3.0 - tpm2_util.c: Fix an issue int variable size was checked against uint - pcr.c: Fix buffer length issue to support all defined hash algorithm ### 4.0.1 - 2019-10-28 tpm2_checkquote: Fix YAML output bug. ### 3.2.1 - 2019-10-10 * Fix invalid memcpy when extracting ECDSA plain signatures. * Fix resource leak on FILE * in hashing routine. * Correct PCR logic to prevent memory corruption bug. * Errata handler fix. ### 4.0 - 2019-09-09 * tpm2_activatecredential: - \--context is now \--credentialedkey-context. - \--key-context is now \--credentialkey-context. - \--Password is now \--credentialedkey-auth. - \--endorse-passwd is now \--credentialkey-auth. - \--in-file is now \--credential-secret. - \--out-file is now \--certinfo-data. - -f becomes -i. - -k becomes -C. - -e becomes -E. * tpm2_certify: - \--halg is now \--hash-algorithm. - \--obj-context is now \--certifiedkey-context. - \--key-context is now \--signingkey-context. - \--pwdo is now \--certifiedkey-auth. - \--pwdk is now \--signingkey-auth. - -a becomes -o. - -k becomes -p. - -c becomes -C. - -k becomes -K. * tpm2_changeauth: - New tool for changing the authorization values of: - Hierarchies - NV - Objects - Replaces tpm2_takeownership with more generic functionality. * tpm2_checkquote: - \--halg is now \--hash-algorithm. - \--pcr-input-file is now \--pcr. - \--pubfile is now \--public. - \--qualify-data is now \--qualification. - -f becomes -F. - -F becomes -f. - -G becomes -g. * tpm2_clear: - \--lockout-passwd is now \--auth-lockout. * tpm2_clearcontrol: - New tool for enabling or disabling tpm2_clear commands. * tpm2_create - \--object-attributes is now \--attributes. - \--pwdp is now \--parent-auth. - \--pwdo is now \--key-auth. - \--in-file is now \--sealing-input. - \--policy-file is now \--policy. - \--pubfile is now \--public. - \--privfile is now \--private. - \--out-context is now \--key-context. - \--halg is now \--hash-algorithm. - \--kalg is now \--key-algorithm. - -o becomes -c. - -K becomes -p. - -A becomes -b. - -I becomes -i. - -g becomes an optional option. - -G becomes an optional option. - Supports TPM command CreateLoaded via -c. * tpm2_createak: - Renamed from tpm2_getpubak * tpm2_createek: - renamed from tpm2_getpubek * tpm2_createpolicy: - \--out-policy-file is now \--policy. - \--policy-digest-alg is now \--policy-algorithm. - \--auth-policy-session is now \--policy-session. - -L becomes -l. - -F becomes -f. - -f becomes -o. - Removed option \--set-list with short option -L. - Removed option \--pcr-input-file with short option -F. - Pcr policy options replaced with pcr password mini language. - Removed short option a for specifying auth session. Use long option \--policy-session. - Removed short option -P for specifying pcr policy. Use long option \--policy-pcr. * tpm2_createprimary: - \--object-attributes is now \--attributes. - -o is now -c - \--pwdp is now \--hierarchy-auth. - \--pwdk is now \--key-auth. - \--halg is now \--hash-algorithm. - \--kalg is now \--key-algorithm. - \--context-object is now \--key-context. - \--policy-file is now \--policy. - support for unique field when creating objects via -u - saves a context file for the generated primary's handle to disk via -c. - -A becomes -a. - -K becomes -p. - -H becomes -C. - -g becomes optional. - -G becomes optional. * tpm2_dictionarylockout: - \--lockout-passwd is now \--auth. - -P becomes -p. * tpm2_duplicate: - New tool for duplicating TPM objects. * tpm2_encryptdecrypt: - \--pwdk is now \--auth. - \--out-file is now \--output. - -D becomes -d. - -I becomes an argument. - -P becomes -p. - Support IVs via -t or \--iv. - Support modes via -G. - Support padding via -e or \--pad. - Supports input and output to stdin and stdout respectively. * tpm2_evictcontrol: - \--auth is now \--hierarchy. - \--context is now \--object-context. - \--pwda is now \--auth. - \--persistent with short option -S is now an argument. - -A becomes -C. - Added option \--output -o to serialize handle to disk. - Removed option \--handle with short option -H. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Removed option \--input-session-handle with short option -i. - Authorization session is now part of password mini language. * tpm2_getcap: - -c becomes an argument. - Most instances of value replaced with raw in YAML output. - TPM2_PT_MANUFACTURER displays string value and raw value. - Supports \--pcr option for listing hash algorithms and bank numbers. * tpm2_getekcertificate: - Renamed from tpm2_getmanufec * tpm2_getmanufec: - Renamed the tool to tpm2_getekcertificate. - Removed ek key creation and management logic. - Added option for getting ek cert for offline platform via -x. - Support for ECC keys. - \--ec-cert is now \--ek-certificate, - \--untrusted is now \--allow-unverified, - \--output is now \--ek-public, - -U is now -X. - -O is now -x. - -f becomes -o. - Removed option -P or \--endorse-passwd. - Removed option -p or \--ek-passwd. - Removed option -w or \--owner-passwd. - Removed option -H or \--persistent-handle. - Removed option -G or \--key-algorithm. - Removed option -N or \--non-persistent. - Removed option -O or \--offline. * tpm2_getpubak: - renamed to tpm2_createak. - -f becomes -p and -f is used for format of public key output. - \--auth-endorse is now \--eh-auth. - \--auth-ak is now \--ak-auth. - \--halg is now \--hash-algorithm. - \--kalg is now \--key-algorithm. - -e becomes -P. - -P becomes -p. - -D becomes -g. - -p becomes -u. - \--context becomes \--ak-context. - \--algorithm becomes \--kalg. - \--digest-alg becomes \--halg. - \--privfile becomes \--private. - remove -k persistant option. Use tpm2_evictcontrol. - Fix -o option to -w. - now saves a context file for the generated primary's handle to disk. - -E becomes -e. - -g changes to -G. - support for non-persistent AK generation. * tpm2_getpubek: - renamed to tpm2_createek - \--endorse-passwd is now \--eh-auth. - \--owner-passwd is now \--owner-auth. - \--ek-passwd is now \--ek-auth. - \--file is now \--public. - \--context is now \--ek-context. - \--algorithm is now \--key-algorithm. - -e is now -P. - -P is now -p. - -p is now -u. - -o is now -w. - -g is now -G. - Support for saving a context file for the generated primary keys handle to disk. - support for non-persistent EK generation. - -f is now -p. - -f support for format of public key output. * tpm2_getrandom: - change default output to binary. - add \--hex option for output to hex format. - \--out-file is now \--output. - bound input request on max hash size per spec, allow -f to override this. * tpm_gettestresult: - new tool for getting test results. * tpm2_hash: - add \--hex for specifying hex output. - default output of hash to stdout. - default output of hash as binary. - remove output of ticket to stdout. - \--halg is now \--hash-algorithm. - \--out-file is now \--output. - -a is now -C. - -H is now -a. * tpm2_hmac: - add -t option for specifying ticket result. - \--out-file is now \--output. - \--auth-key is now \--auth. -\--algorithm is now \--hash-algorithm. - \--pwdk is now \--auth-key. - -C is now -c. - -P is now -p. * tpm2_hierarchycontrol: - new tool added for enabling or disabling the use of a hierarchy and its associated NV storage. * tpm2_import: - \--object-attributes is now \--attributes. - \--auth-parent is now \--parent-auth. - \--auth-key is now \--key-auth. - \--algorithm is now \--key-algorithm. - \--in-file is now \--input. - \--parent-key is now \--parent-context. - \--privfile is now \--private. - \--pubfile is now \--public. - \--halg is now \--hash-algorithm. - \--policy-file is now \--policy. - \--sym-alg-file is now \--encryption-key. - -A is now -b. - -k is now -i. - support OSSL style -passin argument as \--passin for PEM file passwords. - support additional import key types: - RSA1024/2048. - AES128/192/256. - -q changes to -u to align with tpm2_loads public/private output arguments. - Supports setting object name algorithm via -g. - support specifying parent key with a context file. - \--parent-key-handle/-H becomes \--parent-key/-C - Parent public data option is optional and changes from `-K` to `-U`. - Supports importing external RSA 2048 keys via pem files. - Supports ECC Parent keys. * tpm2_incrementalselftest: - Add tool to test support of specific algorithms. * tpm2_listpersistent: - deleted as tpm2_getcap and tpm2_readpublic can be used instead. * tpm2_load: - -o is now -c. - \--context-parent is now \--parent-context. - \--auth-parent is now \--auth. - \--pubfile is now \--public. - \--privfile is now \--private. - \--out-context is now \--key-context. - now saves a context file for the generated primary's handle to disk. - Option `--pwdp` changes to `--auth-parent`. * tpm2_loadexternal: - \--object-attributes is now --attributes. - -o is now -c - \--key-alg is now \--key-algorithm. - \--pubfile is now \--public. - \--privfile is now \--private. - \--auth-key is now \--auth. - \--policy-file is now \--policy. - \--halg is now \--hash-algorithm. - \--out-context is now \--key-context. - Remove unused -P option. - -H is now -a. - Fix -A option to -b for attributes. - now saves a context file for the generated primary's handle to disk. - support OSSL style -passin argument as \--passin for PEM file passwords. - name output to file and stdout. Changes YAML stdout output. - ECC Public and Private PEM support. - AES Public and Private "raw file" support. - RSA Public and Private PEM support. - Object Attribute support. - Object authorization support. - Default hierarchy changes to the *null* hierarchy. * tpm2_makecredential: - \--out-file is now \--credential-blob - \--enckey is now \--encryption-key. - Option `--sec` changes to `--secret`. * tpm2_nvdefine: - \--handle-passwd is now \--hierarchy-auth. - \--index-passwd is now \--index-auth. - \--policy-file is now \--policy. - \--auth-handle is now \--hierarchy. - -a becomes -C. - -t becomes -a. - -I becomes -p. - Removed option \--index with short option -x. It is now an argument. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. * tpm2_nvincrement: - New tool to increment value of a Non-Volatile (NV) index setup as a counter. * tpm2_nvlist: - tpm2_nvlist is now tpm2_nvreadpublic. * tpm2_nvread: - \--handle-passwd is now \--auth. - \--auth-handle is now \--hierarchy. - -a becomes -C. - Removed option \--index with short option -x. It is now an argument. - Removed short option -o for specifying offset. Use long option \--offset. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. - Removed option \--set-list with short option -L. - Removed option \--pcr-input-file with short option -F. - Pcr policy options replaced with pcr password mini language. - fix a buffer overflow. * tpm2_nvreadlock: - \--handle-passwd is now \--auth. - \--auth-handle is now \--hierarchy. - -a becomes -C. - Removed option \--index with short option -x. It is now an argument. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. * tpm2_nvwrite: - \--handle-passwd is now \--auth. - \--auth-handle is now \--hierarchy. - -a becomes -C. - Removed option \--index with short option -x. It is now an argument. - Removed short option -o for specifying offset. Use long option \--offset. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. - Removed option \--set-list with short option -L. - Removed option \--pcr-input-file with short option -F. - Pcr policy options replaced with pcr password mini language. * tpm2_nvrelease: - \--handle-passwd is now \--auth. - \--auth-handle is now \--hierarchy. - -a becomes -C. - Removed option \--index with short option -x. It is now an argument. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. * tpm2_nvundefine: - Renamed from tpm2_nvrelease. * tpm2_pcrallocate: - New tool for changing the allocated PCRs of a TPM. * tpm2_pcrevent: - \--password is now \--auth. - Removed option \--pcr-index with short option -i. - PCR index is now specified as an argument. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. * tpm2_pcrlist: - -gls options go away with -g and -l becoming a single argument. * tpm2_pcrread: - Renamed from tpm2_pcrlist. * tpm2_print: - New tool that decodes a TPM data structure and prints enclosed elements to stdout as YAML. * tpm2_policyauthorize: - New tool that allows for policies to change by associating the policy to a signing authority essentially allowing the auth policy to change. * tpm2_policycommandcode: - New tool to restricts TPM object authorization to specific TPM commands. * tpm2_policyduplicationselect: - New tool for creating a policy to restrict duplication to a new parent and or duplicable object. * tpm2_policylocality: - New tool for creating a policy restricted to a locality. * tpm2_policypcr: - New tool to generate a pcr policy event that bounds auth to specific PCR values in user defined pcr banks and indices. * tpm2_policyor: - New tool to compound multiple policies in a logical OR fashion to allow multiple auth methods using a policy session. * tpm2_policypassword: - New tool to mandate specifying of the object password in clear using a policy session. * tpm2_policysecret: - New tool to associate auth of a reference object as the auth of the new object using a policy session. * tpm2_quote: - \--ak-context is now \--key-context. - \--ak-password is now \--auth. - \--sel-list is now \--pcr-list. - \--qualify-data is now \--qualification-data. - \--pcrs is now \--pcr. - \--sig-hash-algorithm is now \--hash-algorithm. - -P becomes -p - -L becomes -l. - -p becomes -o. - -G becomes -g. - -g becomes optional. - Removed option \--id-list with short option -l. - Removed option \--ak-handle with short option -k. - Raw object-handles and object-contexts are commonly handled with object handling logic. * tpm2_readpublic: - \--opu is now \--output. - \--context-object is now \--object-context. - Removed option \--object with short option -H. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Added \--serialized-handle for saving serialized ESYS_TR handle to disk. - Added \--name with short option -n for saving the binary name. - Supports ECC pem and der file generation. * tpm2_rsadecrypt: - \--pwdk is now \--auth. - \--out-file is now \--output. - -P becomes -p. - Added \--label with short option -l for specifying label. - Added \--scheme with short option -s for specifying encryption scheme. - Removed option -I or in-file input option and make argument. - Removed option \--key-handle with short option -k. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. * tpm2_rsaencrypt: - \--out-file is now \--output. - Added \--scheme with short option -s for specifying encryption scheme. - Added \--label with -l for specifying label. - Removed option \--key-handle with short option -k. - Raw object-handles and object-contexts are commonly handled with object handling logic. - make output binary either stdout or file based on -o. * tpm2_selftest: - New tool for invoking tpm selftest. * tpm2_send: - \--out-file is now \--output. * tpm2_sign: - \--pwdk is now \--auth. - \--halg is now \--hash-algorithm. - \--sig is now \--signature. - -P becomes -p. - -s becomes -o. - Added \--digest with short option -d. - Added \--scheme with short option -s. - Supports rsapss. - Removed option \--key-handle with short option -k. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Removed option \--msg with short option -m. - Make -d toggle if input is a digest. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. - Supports signing a pre-computed hash via -d. * tpm2_startauthsession: - New tool to start/save a trial-policy-session (default) or policy- authorization-session with command line option --policy-session. * tpm2_stirrandom: - new command for injecting entropy into the TPM. * tpm2_takeownership: - split into tpm2_clear and tpm2_changeauth * tpm2_testparms: - new tool for querying tpm for supported algorithms. * tpm2_unseal: - \--pwdk is now \--auth. - \--outfile is now \--output. - \--item-context is now \--object-context. - -P becomes -p - Removed option \--item with short option -H. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Removed option \--input-session-handle with short option -S. - Authorization session is now part of password mini language. - Removed option \--set-list with short option -L. - Removed option \--pcr-input-file with short option -F. - Pcr policy options replaced with pcr password mini language. * tpm2_verifysignature: - \--halg is now \--hash-algorithm. - \--msg is now \--message. - \--sig is now \--signature. - -D becomes -d. - -t becomes optional. - Issue warning when ticket is specified for a NULL hierarchy. - Added option \--format with short option -f. - Removed option \--raw with short option -r. - Removed option \--key-handle with short option -k. - Raw object-handles and object-contexts are commonly handled with object handling logic. - Support routines for OpenSSL compatible format of public keys (PEM, DER) and plain signature data without TSS specific headers. * misc: - cmac algorithm support. - Add support for reading authorisation passwords from a file. - Ported all tools from SAPI to ESAPI. - Load TCTI's by SONAME, not raw .so file. - system tests are now run with make check when --enable-unit is used in configure. - Libre SSL builds fixed. - Dynamic TCTIS. Support for pluggable TCTI modules via the -T or --tcti options. - test: system testing scripts moved into subordinate test directory. - configure: enable code coverage option. - env: add TPM2TOOLS_ENABLE_ERRATA to control the -Z or errata option. affects all tools. - Fix parsing bug in PCR mini-language. - Fix misspelling of TPM2_PT_HR constants which effects tpm2_getcap output. - configure option --with-bashcompdir for specifying bash completion directory. ### 3.2.0 - 2019-06-19 * fix configure bug for linking against libmu. * tpm2_changeauth: Support changing platform hierarchy auth. * tpm2_flushcontext: Introduce new tool for flushing handles from the TPM. * tpm2_checkquote: Introduce new tool for checking validity of quotes. * tpm2_quote: Add ability to output PCR values for quotes. * tpm2_makecredential: add support for executing tool off-TPM. * tpm2_pcrreset: introduce new tool for resetting PCRs. * tpm2_quote: Fix AK auth password not being used. ### 3.1.4 - 2019-03-14 * Fix various man pages * tpm2_getmanufec: fix OSSL build warnings * Fix broken -T option * Various build compatibility fixes * Fix some unit tests * Update build for recent autoconf-archive versions * Install m4 files ### 3.1.3 - 2018-10-15 * Restore support for the TPM2TOOLS_* env vars for TCTI configuration, in addition to supporting the new unified TPM2TOOLS_ENV_TCTI * Fix tpm2_getcap to print properties with the TPM_PT prefix, rather than TPM2_PT * Make test_tpm2_activecredential Python 3 compatible * Fix tpm2_takeownership to only attempt to change the specified hierarchies ### 3.1.2 - 2018-08-14 * Revert the change to use user supplied object attributes exclusively. This is an inappropriate behavioural change for a MINOR version number increment. * Fix inclusion of object attribute specifiers section in tpm2_create and tpm2_createprimary man pages. * Use better object attribute defaults for authentication, preventing an empty password being used for authentication when a policy is set. ### 3.1.1 - 2018-07-09 * Allow man page installation without pandoc being available ### 3.1.0 - 2018-06-21 * Update to use TSS version 2.0 * When user supplies nv attributes use those exclusively, not in addition to the defaults * When user supplies object attributes use those exclusively, not in addition to the defaults * Load TCTI's by SONAME, not raw .so file ### 3.0.4 - 2018-05-30 * Fix save and load for TPM2B_PRIVATE object. * Use a default buffer size for tpm2_nv{read,write} if the TPM reports a 0 size. * Fix --verbose and --version options crossover. * Generate man pages from markdown and include them in the distribution tarball. * Print usage summary if tools are executed with no options or man page can't be displayed. ### 3.0.3 - 2017-15-18 * Tools that don't need a TPM to work no longer request a TPM connection. Namely, tpm2_rc_decode * Fix undefined references in libmarshal port. ### 3.0.2 - 2017-12-18 * configure: enable code coverage option. * build: enable silent rules options. * Add system tests to dist tarball. * tpm2_nv(read|write): fix buffer overflows. ### 3.0.1 - 2017-12-11 * Makefile: add missing LICENSE and markdown files. ### 3.0 - 2017-12-08 * tpm2_getmanufec: -O as a flag for -f has changed. -O is for existing EK public structure and -f is only for generated EK public output. * tpm2_nvlist: output in yaml format. * tpm2_makecredential format changes to the -o output file. * tpm2-quote: -o option removed. * tpm2_rsaencrypt: -I is now an argument and input defaults to stdin. -o is optional and defaults to stdout. * tpm2_listpersistent: output friendly object attributes. * tpm2_createprimary: support friendly object attributes via -A. -H becomes auth hierarchy. * tpm2_create: support friendly object attributes via -A. * tpm2_nvwrite and tpm2_nvread have support for satisfying PCR policies. * tpm2_encryptdecrypt: has support for EncryptDecrypt2 command. * tpm2_nvwrite: -f option removed, support for stdin data supported. Support for starting index to write to. * errata framework added for dealing with spec errata. * tpm2_quote: -G option for signature hash algorithm specification. * tpm2_dump_capability: renamed to tpm2_getcap. * tpm2_send_command: renamed to tpm2_send and the input file is now an argument vs using -i. * tpm2_dump_capability: outputs human readable command codes. * camelCase options are now all lower case. For example, --camelCase becomes --camel-case. * tpm2_quote,readpublic, and sign now have support for pem/der output/inputs. See the respective man pages for more details. * tpm2_nvread: Has an output file option, -f. * manpages: Are now in Markdown and converted to roff using pandoc. * tpm2_create - options 'o' and 'O' changed to 'u' and 'r' respectively. * tpm2_pcrlist: support yaml output for parsing. * tpm2_pcrevent: new tool for hashing and extending pcrs. * Make tpm2_{createprimary,create,load,pcrlist,hmac} tools to support the --quiet option. * Support for a --quiet option to suppress messages printed by tools to standard output. * tpm2_hmac: support for files greater than 1024 bytes, changes in options and arguments. * tpm2_hash: support for files greater than 1024 bytes, changes in options and arguments. * Install is now to bin vs sbin. Ensure that sbin tools get removed! * make dist and distcheck are now working. * installation into customized locations are now working, see issue #402 for details. * tpm2_pcrlist: renamed from tpm2_listpcrs. * tpm2_pcrextend: new tool for extending PCRs. * tpm2_getmanufec: -E option no longer required, defaults to stdout. * tpm2_nvlist: Support for friendly nv attributes in output. * Support for friendly algorithm names for algorithm identifiers. * tpm2_nvread: The option, -s, or size option is no longer required. * tpm2_nvwrite: fixed to write files larger than 1024 in size. * tpm2_nvread: fixed to read files larger than 1024 in size. * tpm2_nvdefine supports "nice-names" for nv space attributes. * Support using PCR Policy directly with tpm2_unseal tool. * Support PCR policy creation in tpm2_createpolicy * Support using a policy session as input to tools that may need to satisfy complex policies other than password. * tpm2_unseal: supports output to stdoud. * tpm2_create: enforce policy based authorization. * tpm2_createprimary: add ability to create objects with policy based authorization. * tpm2_nvdefine: add ability to create nv indexes with policy based authorization. * Support Clang Build. * tpm2_unseal test uses endorsement hierarchy as platform hierarchy is unavailable on a real tpm. * Numerous cleanups and minor bug fixes. ### v2.0 - 2017-03-29 * Tracked on the milestone: https://github.com/tpm2-software/tpm2-tools/milestone/2 * Reworked all the tools to support configurable TCTIs, based on build time configuration, one can specify the tcti via the --tcti (-T) option to all tools. * tpm2_getrandom interface made -s a positional argument. * Numerous bug fixes. ### v1.1 - 2016-11-04 * travis ci support. * Allow for unit tests to be enabled selectively. * tpm2_rc_decode tool: Decode TPM_RC error codes. * Android Make file * tpm2_listpersistent: list all persistent objects * test scripts for tpm2-tools * tpm2_nvreadlock * tpm2_getmanufec: retrieve EC from tpm manufacturer server. * Copy 'common' and 'sample' code from the TPM2.0-TSS repo. **Modified** * tpm2_takeownership: update option -c to use lockout password to clear. * tpm2_listpcrs: add options -L and -s, rewrite to increase performance. * tpm2_quote: added -L option to support selection of multiple banks. * tpm2_quote: add -q option to get qualifying data. * configure: Use pkg-config to get info about libcurl and libcrypto. * configure: Use pkg-config to locate SAPI and TCTI headers / libraries. * tpm2_x: Add -X option to enable password input in Hex format. * tpm2_nvdefine: Change -X option to -I. * tpm2-nvwrite: fix for unable to write 1024B+ data. * tpm2_getmanufec: Fix base64 encoding. * tpm2_x: fixed a lot of TPM2B failures caused by wrong initialization. * tpm2_getmanufec: let configure handle libs. * tpm2_getmanufec: Convert from dos to unix format. * build: Check for TSS2 library @ configure time. * build: Detect required TSS2 and TCTI headers. * build: Use libtool to build the common library * build: Install all binaries into sbin. * build: Build common sources into library. * build: Move all source files to 'src'. * Makefile.am: Move all build rules into single Makefile.am. * everything: Use new TCTI headers and fixup API calls. * everything: Update source to cope with sapi header cleanup. * tpm2_activatecredential: Updated to support TCG compatible EK * tpm2_getpubak: Updated to use TCG compatible EK * tpm2_getpubek: fix ek creation to follow TCG EK profile spec. **Removed** * Windows related code * dependency on the TPM2.0-TSS repo source code ### v1.0 - 2015-10-19 * 1.0 release * 29 tools included tpm2-tools-5.2/doc/CONTRIBUTING.md000066400000000000000000000022161412464516500164070ustar00rootroot00000000000000## Guidelines for submitting bugs: All non security bugs can be filed on the Issues tracker: Security sensitive bugs should be emailed to a maintainer or to Intel via the guidelines here: ## Guidelines for submitting changes: All changes should be introduced via github pull requests. This allows anyone to comment and provide feedback in lieu of having a mailing list. For pull requests opened by non-maintainers, any maintainer may review and merge that pull request. For maintainers, they either must have their pull request reviewed by another maintainer if possible, or leave the PR open for at least 24 hours, we consider this the window for comments. All tests must pass on Travis CI for the merge to occur. All changes must not introduce superfluous whitespace changes or whitespace errors. All changes should adhere to the coding standard documented under misc. ### Guideline for merging changes: Changes should be merged with the "rebase" option on github to avoid merge commits. This provides for a clear linear history. tpm2-tools-5.2/doc/INSTALL.md000066400000000000000000000154421412464516500156130ustar00rootroot00000000000000## Building tpm2-tools Below you will find instructions to build and install the tpm2-tools project. ### Download the Source To obtain the tpm2-tools sources you must clone them as below: ``` git clone https://github.com/tpm2-software/tpm2-tools ``` ### Dependencies To build and install the tpm2-tools software the following software is required: * GNU Autoconf (version >= 2019.01.06) * GNU Automake * GNU Libtool * pkg-config * C compiler * C Library Development Libraries and Header Files (for pthreads headers) * ESAPI - TPM2.0 TSS ESAPI library (tss2-esys) and header files * OpenSSL libcrypto library and header files (version >= 1.1.0) * Curl library and header files #### Optional Dependencies: * To build the man pages you need [pandoc](https://github.com/jgm/pandoc) * FAPI - TPM2.0 TSS FAPI library (tss2-fapi) and header files * To enable the new userspace resource manager, one must get tpm2-tabrmd (**recommended**). * When ./configure is invoked with --enable-unit or --enable-unit=abrmd, the tests are run towards a resource manager, tpm2-abrmd, which must be on $PATH. * When ./configure is invoked with --enable-unit=mssim, the tests are run directly towards tpm_server, without resource manager. * For the tests, with or without resource manager, tpm_server must be installed. * Some tests pass only if xxd, expect, bash and python with PyYAML are available * Some tests optionally use (but do not require) curl ### Typical Distro Dependency Installation Here we are going to satisfy tpm2-tools dependencies with: * tpm2-tss: * tpm2-abrmd: * TPM simulator: Which are necessary for the build example section at the bottom of this file, we need to satisfy the dependencies for each item named above except for the simulator. #### Ubuntu 16.04 Satisfying the dependencies for tpm2-tools falls into two general steps, stuff you can easily get via the package manager, and stuff you cannot. **NOTE**: The *tpm2 Userspace Dependencies* may not be the correct version in your distros package manager. **Packages**: The packages in the below command can be ascertained via the package manager. ``` sudo apt-get install autoconf automake libtool pkg-config gcc \ libssl-dev libcurl4-gnutls-dev python-yaml ``` **Notes**: * One can substitute gcc for clang if they desire. * On pre-ubuntu 16.04 `libcurl4-gnutls-dev` was provided by `libcurl-dev` * The libcurl dependency can be satisfied in many ways, and likely change with Ubuntu versions: * `libcurl4-openssl-dev 7.47.0-1ubuntu2.2` * `libcurl4-nss-dev 7.47.0-1ubuntu2.2` * `libcurl4-gnutls-dev 7.47.0-1ubuntu2.2` * One needs autoconf archive, which is too old in the packagemanager. You can get working version from [here](http://ftpmirror.gnu.org/autoconf-archive/autoconf-archive-2019.01.06.tar.xz) **tpm2 Userspace Dependencies**: The following tpm2 userspace dependencies can be satisfied by getting the source, building and installing them. They can be located here: * ESAPI - The enhanced system API: * ABRMD (**recommended but optional**) - Which is the userspace resource manager: #### Fedora In case you want to build from source the next command block should cover all the dependencies for tpm2-tools, the enhanced system API (tpm2-tss) and the userspace resource manager (tpm2-abrmd). ``` $ sudo dnf -y update && sudo dnf -y install automake libtool \ autoconf autoconf-archive libstdc++-devel gcc pkg-config \ uriparser-devel libgcrypt-devel dbus-devel glib2-devel \ compat-openssl10-devel libcurl-devel PyYAML ``` Some distros have the dependencies already packaged, you can simply install the package that contains the needed build requirements. ``` $ sudo dnf builddep tpm2-tools ``` The package installed above contains all the dependencies for tpm2-tools included the projects mentioned at the beginning of this section (tpm2-tss and tpm2-abrmd) For more detailed information about the dependencies of tpm2-tss and tmp2-abrmd, please consult the corresponding links for each project. You can find these links in the [Dependency-Matrix](https://tpm2-software.github.io/versions/) ## Building To compile tpm2-tools execute the following commands from the root of the source directory: ``` $ ./bootstrap $ ./configure $ make ``` This is sufficient for running as long as you alter `PATH` so that it points to the *tools* directory, or just execute them via a full path. For Example: ``` ./tools/tpm2_getrandom 4 ``` ### Building from source example Now we can start building the projects, there are four major steps for building the projects from source: #### Bootstrapping the build With the bootstrap command we run a script which generates the list of source files along with the configure script. In the project directory: ``` $ ./bootstrap ``` #### Configuring the build Here we run the configure script, this generates the makefiles needed for the compilation. ``` $ ./configure ``` Depending of the project, you can add additional information to the configure script, please refer to the links provided below for more information about the custom options. * Default values for GNU installation directories: * Custom options for tpm2-tss: * Custom options for tpm2-abrmd: #### Compiling the Libraries We use the make command for compile the code. ``` $ make -j$(nproc) ``` #### Installing the Libraries Once we have finish building the projects it's time to install them. ``` $ sudo make install ``` Now putting all together: * ##### Tpm2-tss ``` $ git clone https://github.com/tpm2-software/tpm2-tss.git $ cd tpm2-tss $ ./bootstrap $ ./configure --prefix=/usr $ make -j5 $ sudo make install ``` * ##### Tpm2-abrmd ``` $ git clone https://github.com/tpm2-software/tpm2-abrmd.git $ cd tpm2-abrmd $ ./bootstrap $ ./configure --with-dbuspolicydir=/etc/dbus-1/system.d --with-udevrulesdir=/usr/lib/udev/rules.d --with-systemdsystemunitdir=/usr/lib/systemd/system --libdir=/usr/lib64 --prefix=/usr $ make -j5 $ sudo make install ``` * ##### Tpm2-tools ``` $ git clone https://github.com/tpm2-software/tpm2-tools.git $ cd tpm2-tools $ ./bootstrap $ ./configure --prefix=/usr $ make -j5 $ sudo make install ``` * ##### TPM simulator ``` $ mkdir ibmtpm && cd ibmtpm $ wget https://sourceforge.net/projects/ibmswtpm2/files/latest/download -O ibmtpm.tar.gz $ tar -zxvf ibmtpm.tar.gz $ cd src $ make -j5 ``` And it's done, you are ready to run the projects. tpm2-tools-5.2/doc/LICENSE000066400000000000000000000036471412464516500151740ustar00rootroot00000000000000Copyright 2017 Alibaba Group Copyright 2015-2017 Atom Software Studios, s.r.o. Copyright 2017 Emmanuel Deloget Copyright 2018-2019 Fraunhofer SIT Copyright 2019 Fraunhofer SIT sponsored by Infineon Technologies AG Copyright 2019 GlovePuppet Copyright 2015-2019 Intel Corporation Copyright 2019 Massachusetts Institute of Technology Copyright 2017-2018 National Instruments Copyright 2017 Red Hat, Inc. Copyright 2019 Sebastien LE STUM Copyright 2017 SUSE GmbH Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. 3. Neither the name of the copyright holder 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. tpm2-tools-5.2/doc/MAINTAINERS.md000066400000000000000000000001461412464516500162520ustar00rootroot00000000000000## Maintainers * William Roberts * Imran Desai tpm2-tools-5.2/doc/README.md000066400000000000000000000051461412464516500154420ustar00rootroot00000000000000[![Build Status](https://github.com/tpm2-software/tpm2-tools/workflows/CI/badge.svg)](https://github.com/tpm2-software/tpm2-tools/actions) [![FreeBSD Build Status](https://api.cirrus-ci.com/github/tpm2-software/tpm2-tools.svg?branch=master)](https://cirrus-ci.com/github/tpm2-software/tpm2-tools) [![codecov](https://codecov.io/gh/tpm2-software/tpm2-tools/branch/master/graph/badge.svg)](https://codecov.io/gh/tpm2-software/tpm2-tools) [![Coverity Scan](https://img.shields.io/coverity/scan/3997.svg)](https://scan.coverity.com/projects/01org-tpm2-0-tools) [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/tpm2-software/tpm2-tools.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/tpm2-software/tpm2-tools/context:cpp) **This site contains the code for the TPM (Trusted Platform Module) 2.0 tools based on tpm2-tss** ## Build and Installation instructions: Instructions for building and installing the tpm2-tools are provided in the [INSTALL.md](INSTALL.md) file. ## Release Procedures Instructions for how releases are conducted, including our QA practices, please see the [RELEASE.md](RELEASE.md) file. ## Support Please use the mailing list at https://lists.01.org/postorius/lists/tpm2.lists.01.org/ for general questions. The Issue Tracker on github should be reserved for actual feature requests or bugs. For security bugs, please see [CONTRIBUTING.md](CONTRIBUTING.md) for information on how to submit those. ## Resources Reference the tutorials at [tpm2-software.github.io](https://tpm2-software.github.io). TPM 2.0 specifications can be found at [Trusted Computing Group](http://www.trustedcomputinggroup.org/). Specifically, the following sections: ### The Library Specification This specifies the external programatic interface to the TPM: ### The Enhanced System API Specification This is the *ESAPI* dependency mentioned in [INSTALL.md](INSTALL.md). This is the enhanced software API to the tpm. The tpm2-tools project relies heavily on this. ### The TCTI Specification This specifies the transmission interfaces or how bytes get from the system api to the tpm. ### Books * [A Practical Guide to TPM 2.0](https://link.springer.com/book/10.1007%2F978-1-4302-6584-9) `ISBN: 978-1-4302-6583-2 (Print) 978-1-4302-6584-9 (Online)` ## Contributing Instructions for contributing to the project are provided in the [CONTRIBUTING.md](CONTRIBUTING.md) file. tpm2-tools-5.2/doc/RELEASE.md000066400000000000000000000207201412464516500155600ustar00rootroot00000000000000# Release Lifecycle All tpm2-tools project releases before 4.0 is considered legacy and is or will be reaching end of life. Releases greater than 4.0 will always **will be backwards compatible**. Thus, based on the semver.org rules outlined, pretty much dictates we will never be off of a 4.X version number. Because of this, master will always be the *next* release, and bugfix only releases can be branched off of *master* as needed. These patch level branches will be supported on an as needed bases, since we don't have dedicated stable maintainers. The majority of development will occur on *master* with tagged release numbers following semver.org recommendations. This page explicitly does not formalize an LTS support timeline, and that is intentional. The release schedules and required features are driven by community involvement and needs. However, milestones will be created to outline the goals, bugs, issues and timelines of the next release. ## End Of Life versions - [1.X](https://github.com/tpm2-software/tpm2-tools/tree/1.X) - [2.X](https://github.com/tpm2-software/tpm2-tools/tree/2.X) - [3.0.X](https://github.com/tpm2-software/tpm2-tools/tree/3.0.X) ## Near End of Life - [3.0.X](https://github.com/tpm2-software/tpm2-tools/tree/3.0.X): EOL after 3.2.1 release. # Release Information Releases shall be tagged following semantic version guidelines found at: - http://semver.org/ The general release process will be one of two models: - Tag releases off of branch master. - Tag releases off of a release specific branch. - Release specific branch names can be for long-running major versions, IE 3.1, 3.2, 3.3, etc. and *SHALL* be named `.X`. - Release specific branch names can be for long-running minor versions, IE 3.1.1, 3.1.2, etc. and *SHALL* be named `..X`. Release candidates will be announced on the [mailing list](https://lists.01.org/mailman/listinfo/tpm2). When a RC has gone 1 week without new substantive changes, a release will be conducted. Substantive changes are generally not editorial in nature and they do not contain changes to the CI system. Substantive changes are changes to the man-pages, code or tests. When a release is cut, the process is the same as a Release Candidate (RC), with the exception that it is not marked as "pre-release" on GitHub. The release notes should include everything from the last release to the latest release. ## Updating the CHANGELOG for release candidates and final releases When a first release candidate is cut, a new entry will be added to the CHANGELOG file. This entry will have the release candidate version and the date on which the release candidate was released. The entry will list all the changes that happened between the latest final release and the first release candidate. The commit that made the change will be tagged with a release version and a -rc0 suffix as an indication that is not a final release but a first release candidate. If after a week the -rc has no changes, then a final release can be made as explained above. But if changes are made, then a new releases candidate will be released and the -rc suffix will be incremented. For each release candidate, the changes that happened between the previous release candidate will be appended to the CHANGELOG entry, and both the release candidate version and the date of the release will be updated to reflect the latest release candidate. The commit that updated the CHANGELOG entry will be tagged as the latest release candidate. When a final version will be released, there will not be changes to append to the CHANGELOG entry since otherwise a new release candidate should be cut. So only the release version and date should be updated in the CHANGELOG. The commit that updated the CHANGELOG entry will be tagged as the final release. For a final release, change the version to the final release version (i.e: 3.0.5-rc3 -> 3.0.5) and update the date. The commit for this change will be tagged as $version. ## Testing The tools code **MUST** pass the Travis CI testing and have a clean Coverity scan result performed on every release. The CI testing not only tests for valid outputs, but also runs tests uses clang's ASAN feature to detect memory corruption issues. - BUG: Reconfigure Coverity: https://github.com/tpm2-software/tpm2-tools/issues/1727 ## Release Checklist The steps, in order, required to make a release. - Ensure current HEAD is pointing to the last commit in the release branch. - Ensure [Travis](https://travis-ci.org/tpm2-software/tpm2-tools) has conducted a passing build of HEAD. - Update version and date information in [CHANGELOG.md](CHANGELOG.md) **and** commit. - Create a signed tag for the release. Use the version number as the title line in the tag commit message and use the [CHANGELOG.md](CHANGELOG.md) contents for that release as the body. ```bash git tag -s ``` - Build a tarball for the release and check the dist tarball. **Note**: The file name of the tarball should include a match for the git tag name. ```bash make distcheck ``` - Generate a detached signature for the tarball. ```bash gpg --armor --detach-sign ``` - Push **both** the current git HEAD (should be the CHANGELOG edit) and tag to the release branch. ```bash git push origin HEAD: git push origin ``` - Verify that the Travis CI build passes. **Note**: Travis will have two builds, one for the push to master and one for the tag push. Both should succeed. - Create a release on [Github](https://github.com/tpm2-software/tpm2-tools/releases), using the `` uploaded. If it is a release candidate, ensure you check the "pre-release" box on the GitHub UI. Use the [CHANGELOG.md](CHANGELOG.md) contents for that release as the message for the GitHub release. **Add the dist tarball and signature file to the release**. - Update the [dependency-matrix](https://tpm2-software.github.io/versions/) ensuring that the CI is building against a released version of: - [tpm2-abrmd](https://github.com/tpm2-software/tpm2-abrmd) - [tpm2-tss](https://github.com/tpm2-software/tpm2-tss) Configuration can be modified via [docker-prelude.sh](.ci/docker-prelude.sh). - After the release (not a release candidate) add a commit to master updating the News section of the [README](README.md) to point to the latest release. - Send announcement on [mailing list](https://lists.01.org/mailman/listinfo/tpm2). ## Historical Version Information Versions after v1.1.0 will no longer have the "v" prefix. Autoconf now sets the VERSION #define based on the output of git describe. See commit 2e8a07bc for the details. Version tags after v1.1.0 shall be signed. ## Verifying git signature Valid known public keys can be reached by referencing the annotated tags listed below: - william-roberts-pub - javier-martinez-pub - joshua-lock-pub - idesai-pub or via a PGP public keyring server like: - http://keyserver.pgp.com/vkd/GetWelcomeScreen.event Import the key into your keyring: ``` $ git show [annotated-tag-name] | gpg --import ``` **Example**: ``` $ git show william-roberts-pub | gpg --import ``` Verify the release tag: ``` $ git tag --verify [signed-tag-name] ``` # Local Release Configuration Below you will find information how to configure your machine locally to conduct releases. ## Signing Key Setup Signing keys should have these four properties going forward: - belong to a project maintainer. - be discoverable using a public GPG key server. - be [associated]((https://help.github.com/articles/adding-a-new-gpg-key-to-your-github-account/)) with the maintainers GitHub account. - be discoverable via an annotated tag within the repository itself. Ensure you have a key set up: ``` $ gpg --list-keys ``` If you don't generate one: ``` $ gpg --gen-key ``` Add that key to the gitconfig: ```bash git config user.signingkey [gpg-key-id] ``` Make sure that key is reachable as an object in the repository: ```bash gpg -a --export [gpg-key-id] | git hash-object -w --stdin [object SHA] git tag -a [your-name-here]-pub [object SHA] ``` Make sure you push the tag referencing your public key: ```bash git push origin [your-name-here]-pub ``` Make sure you publish your key by doing: - http://keyserver.pgp.com/vkd/GetWelcomeScreen.event - Select "Publish your key". - Select "Key block" - Copy and paste the output of `gpg --armor --export ` - Validate your email account. After that, you can sign tags: ```bash git tag --sign [signed-tag-name] ``` tpm2-tools-5.2/doc/man000077700000000000000000000000001412464516500155572../manustar00rootroot00000000000000tpm2-tools-5.2/lib/000077500000000000000000000000001412464516500141565ustar00rootroot00000000000000tpm2-tools-5.2/lib/.gitignore000066400000000000000000000000451412464516500161450ustar00rootroot00000000000000* !*/ !.gitignore !*.c !*.h config.h tpm2-tools-5.2/lib/efi_event.h000066400000000000000000000145561412464516500163060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TCG_EFI_EVENT_H #define TCG_EFI_EVENT_H 1 #include #include /* * Log event types. These are spread out over 2 specs: * "TCG EFI Protocol Specification For TPM Family 1.1 or 1.2" and * "TCG PC Client Specific Implementation Specification for Conventional BIOS" */ #define EV_PREBOOT_CERT 0x0 #define EV_POST_CODE 0x1 #define EV_UNUSED 0x2 #define EV_NO_ACTION 0x3 #define EV_SEPARATOR 0x4 #define EV_ACTION 0x5 #define EV_EVENT_TAG 0x6 #define EV_S_CRTM_CONTENTS 0x7 #define EV_S_CRTM_VERSION 0x8 #define EV_CPU_MICROCODE 0x9 #define EV_PLATFORM_CONFIG_FLAGS 0xa #define EV_TABLE_OF_DEVICES 0xb #define EV_COMPACT_HASH 0xc #define EV_IPL 0xd #define EV_IPL_PARTITION_DATA 0xe #define EV_NONHOST_CODE 0xf #define EV_NONHOST_CONFIG 0x10 #define EV_NONHOST_INFO 0x11 #define EV_OMIT_BOOT_DEVICE_EVENTS 0x12 /* TCG EFI Platform Specification For TPM Family 1.1 or 1.2 */ #define EV_EFI_EVENT_BASE 0x80000000 #define EV_EFI_VARIABLE_DRIVER_CONFIG EV_EFI_EVENT_BASE + 0x1 #define EV_EFI_VARIABLE_BOOT EV_EFI_EVENT_BASE + 0x2 #define EV_EFI_BOOT_SERVICES_APPLICATION EV_EFI_EVENT_BASE + 0x3 #define EV_EFI_BOOT_SERVICES_DRIVER EV_EFI_EVENT_BASE + 0x4 #define EV_EFI_RUNTIME_SERVICES_DRIVER EV_EFI_EVENT_BASE + 0x5 #define EV_EFI_GPT_EVENT EV_EFI_EVENT_BASE + 0x6 #define EV_EFI_ACTION EV_EFI_EVENT_BASE + 0x7 #define EV_EFI_PLATFORM_FIRMWARE_BLOB EV_EFI_EVENT_BASE + 0x8 #define EV_EFI_HANDOFF_TABLES EV_EFI_EVENT_BASE + 0x9 #define EV_EFI_VARIABLE_AUTHORITY EV_EFI_EVENT_BASE + 0xe0 #ifndef PACKED #define PACKED __attribute__((__packed__)) #endif /* GUIDs used by UEFI/GPT are stored in a mixed-endian layout, where the first * three fields are serialized as little-endian and the final two fields are * serialized as big-endian. This differs from uuid_t which is entirely a * big-endian layout (just an array of 16 bytes). */ typedef struct { UINT32 Data1; UINT16 Data2; UINT16 Data3; UINT8 Data4[8]; } PACKED EFI_GUID; typedef struct { UINT16 AlgorithmId; UINT8 Digest[]; } PACKED TCG_DIGEST2; typedef struct { UINT32 EventSize; UINT8 Event []; } PACKED TCG_EVENT2; typedef struct { UINT32 PCRIndex; UINT32 EventType; UINT32 DigestCount; TCG_DIGEST2 Digests []; /* TCG_EVENT2 comes next */ } PACKED TCG_EVENT_HEADER2; /* Helper structure for dealing with unaligned char16_t */ typedef struct { char16_t c; } PACKED UTF16_CHAR; typedef struct { EFI_GUID VariableName; UINT64 UnicodeNameLength; UINT64 VariableDataLength; UTF16_CHAR UnicodeName[]; /* INT8 VariableData[] comes next */ } PACKED UEFI_VARIABLE_DATA; typedef UINT64 UEFI_PHYSICAL_ADDRESS; typedef struct { UEFI_PHYSICAL_ADDRESS BlobBase; UINT64 BlobLength; } PACKED UEFI_PLATFORM_FIRMWARE_BLOB; typedef struct { UINT32 pcrIndex; UINT32 eventType; BYTE digest[20]; UINT32 eventDataSize; BYTE event[]; } PACKED TCG_EVENT; typedef struct { UINT16 algorithmId; UINT16 digestSize; } PACKED TCG_SPECID_ALG; typedef struct { UINT8 vendorInfoSize; BYTE vendorInfo[]; } PACKED TCG_VENDOR_INFO; typedef struct { BYTE Signature[16]; UINT32 platformClass; UINT8 specVersionMinor; UINT8 specVersionMajor; UINT8 specErrata; UINT8 uintnSize; UINT32 numberOfAlgorithms; TCG_SPECID_ALG digestSizes[]; /* then TCG_VendorStuff */ } PACKED TCG_SPECID_EVENT; typedef struct { UEFI_PHYSICAL_ADDRESS ImageLocationInMemory; UINT64 ImageLengthInMemory; UINT64 ImageLinkTimeAddress; UINT64 LengthOfDevicePath; BYTE DevicePath[]; } PACKED UEFI_IMAGE_LOAD_EVENT; /* These structs represent a GUID Partition Table. UEFI_GPT_DATA is defined in the TGC PC Client Platform Firmware Profile Specification Version 1.05, Revision 23, Table 10. UEFI_PARTITION_TABLE_HEADER and UEFI_PARTITION_ENTRY are defined in the UEFI Specification Version 2.9, Section 5.3. */ typedef struct { UINT64 Signature; UINT32 Revision; UINT32 HeaderSize; UINT32 HeaderCRC32; UINT32 Reserved; UINT64 MyLBA; UINT64 AlternateLBA; UINT64 FirstUsableLBA; UINT64 LastUsableLBA; EFI_GUID DiskGUID; UINT64 PartitionEntryLBA; UINT32 NumberOfPartitionEntries; UINT32 SizeOfPartitionEntry; UINT32 PartitionEntryArrayCRC32; } PACKED UEFI_PARTITION_TABLE_HEADER; typedef struct { EFI_GUID PartitionTypeGUID; EFI_GUID UniquePartitionGUID; UINT64 StartingLBA; UINT64 EndingLBA; UINT64 Attributes; /* To make the entire struct 128 bytes, PartitionName is 36 characters. */ UTF16_CHAR PartitionName[36]; } PACKED UEFI_PARTITION_ENTRY; typedef struct { UEFI_PARTITION_TABLE_HEADER UEFIPartitionHeader; UINT64 NumberOfPartitions; UEFI_PARTITION_ENTRY Partitions[]; } PACKED UEFI_GPT_DATA; /* * An UEFI signature database is represented as a concatenated list of * EFI_SIGNATURE_LIST, which contains one or more EFI_SIGNATURE_DATA. These * structs are described in more details in UEFI Spec Section 32.4.1 */ typedef struct { EFI_GUID SignatureType; UINT32 SignatureListSize; UINT32 SignatureHeaderSize; UINT32 SignatureSize; // BYTE SignatureHeader[SignatureHeaderSize]; // BYTE Signatures[][SignatureSize]; } PACKED EFI_SIGNATURE_LIST; typedef struct { EFI_GUID SignatureOwner; BYTE SignatureData[]; } PACKED EFI_SIGNATURE_DATA; /* * EFI_LOAD_OPTION describes a load option variable. This struct is described * in more details in UEFI Spec Section 3.1.3 */ typedef struct { UINT32 Attributes; UINT16 FilePathListLength; UINT16 Description[]; // EFI_DEVICE_PATH_PROTOCOL FilePathList[]; // UINT8 OptionalData[]; } PACKED EFI_LOAD_OPTION; /* * EV_NO_ACTION_STRUCT is the structure of an EV_NO_ACTION event. * Described in TCG PCClient PFP section 9.4.5. * The Signature identifies which arm of the union applies. */ typedef struct { BYTE Signature[16]; union { BYTE StartupLocality; } Cases; } PACKED EV_NO_ACTION_STRUCT; static const BYTE STARTUP_LOCALITY_SIGNATURE[16] = {0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x69, 0x74, 0x79, 0}; #endif tpm2-tools-5.2/lib/files.c000066400000000000000000000603721412464516500154340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" /** * This is the magic for the file header. The header is organized * as a big endian U32 (BEU32) of MAGIC followed by a BEU32 of the * version number. Tools can define their own, individual file * formats as they make sense, but they should always have the header. */ static const UINT32 MAGIC = 0xBADCC0DE; #define BAIL_ON_NULL(param, x) \ do { \ if (!x) { \ LOG_ERR(param" must be specified"); \ return false; \ } \ } while(0) /** * Writes size bytes to a file, continuing on EINTR short writes. * @param f * The file to write to. * @param data * The data to write. * @param size * The size, in bytes, of that data. * @return * True on success, False otherwise. */ static bool writex(FILE *f, UINT8 *data, size_t size) { size_t wrote = 0; size_t index = 0; do { wrote = fwrite(&data[index], 1, size, f); if (wrote != size) { if (errno != EINTR) { return false; } /* continue on EINTR */ } size -= wrote; index += wrote; } while (size > 0); return true; } /** * Reads size bytes from a file, continuing on EINTR short reads. * @param f * The file to read from. * @param data * The data buffer to read into. * @param size * The size of the buffer, which is also the amount of bytes to read. * @return * The number of bytes that have been read. */ static size_t readx(FILE *f, UINT8 *data, size_t size) { size_t bread = 0; do { bread += fread(&data[bread], 1, size-bread, f); } while (bread < size && !feof(f) && errno == EINTR); return bread; } bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path) { long current = ftell(fp); if (current < 0) { if (path) { LOG_ERR("Error getting current file offset for file \"%s\" error: " "%s", path, strerror(errno)); } return false; } int rc = fseek(fp, 0, SEEK_END); if (rc < 0) { if (path) { LOG_ERR("Error seeking to end of file \"%s\" error: %s", path, strerror(errno)); } return false; } long size = ftell(fp); if (size < 0) { if (path) { LOG_ERR("ftell on file \"%s\" failed: %s", path, strerror(errno)); } return false; } rc = fseek(fp, current, SEEK_SET); if (rc < 0) { if (path) { LOG_ERR( "Could not restore initial stream position for file \"%s\" " "failed: %s", path, strerror(errno)); } return false; } /* size cannot be negative at this point */ *file_size = (unsigned long) size; return true; } bool file_read_bytes_from_file(FILE *f, UINT8 *buf, UINT16 *size, const char *path) { unsigned long file_size; bool result = files_get_file_size(f, &file_size, path); if (!result) { /* get_file_size() logs errors */ return false; } /* max is bounded on *size */ if (file_size > *size) { if (path) { LOG_ERR( "File \"%s\" size is larger than buffer, got %lu expected " "less than or equal to %u", path, file_size, *size); } return false; } /* The reported file size is not always correct, e.g. for sysfs files generated on the fly by the kernel when they are read, which appear as having size 0. Read as many bytes as we can until EOF is reached or the provided buffer is full. As a small sanity check, fail if the number of bytes read is smaller than the reported file size. */ *size = readx(f, buf, *size); if (*size < file_size) { if (path) { LOG_ERR("Could not read data from file \"%s\"", path); } return false; } return true; } bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size) { if (!buf || !size || !path) { return false; } FILE *f = fopen(path, "rb"); if (!f) { LOG_ERR("Could not open file \"%s\" error %s", path, strerror(errno)); return false; } bool result = file_read_bytes_from_file(f, buf, size, path); fclose(f); return result; } bool files_save_bytes_to_file(const char *path, UINT8 *buf, UINT16 size) { if (!buf) { return false; } if (!path && !output_enabled) { return true; } FILE *fp = path ? fopen(path, "wb+") : stdout; if (!fp) { LOG_ERR("Could not open file \"%s\", error: %s", path, strerror(errno)); return false; } bool result = files_write_bytes(fp, buf, size); if (!result) { LOG_ERR("Could not write data to file \"%s\"", path ? path : ""); } if (fp != stdout) { fclose(fp); } return result; } /* * Current version to write TPMS_CONTEXT to disk. */ #define CONTEXT_VERSION 1 bool files_save_context(TPMS_CONTEXT *context, FILE *stream) { /* * Saving the TPMS_CONTEXT structure to disk, format: * TPM2.0-TOOLS HEADER * U32 hierarchy * U32 savedHandle * U64 sequence * U16 contextBlobLength * BYTE[] contextBlob */ bool result = files_write_header(stream, CONTEXT_VERSION); if (!result) { LOG_ERR("Could not write context file header"); goto out; } // UINT32 result = files_write_32(stream, context->hierarchy); if (!result) { LOG_ERR("Could not write hierarchy"); goto out; } result = files_write_32(stream, context->savedHandle); if (!result) { LOG_ERR("Could not write savedHandle"); goto out; } LOG_INFO("Save TPMS_CONTEXT->savedHandle: 0x%x", context->savedHandle); // UINT64 result = files_write_64(stream, context->sequence); if (!result) { LOG_ERR("Could not write sequence"); goto out; } // U16 LENGTH result = files_write_16(stream, context->contextBlob.size); if (!result) { LOG_ERR("Could not write contextBob size"); goto out; } // BYTE[] contextBlob result = files_write_bytes(stream, context->contextBlob.buffer, context->contextBlob.size); if (!result) { LOG_ERR("Could not write contextBlob buffer"); } /* result is set by file_write_bytes() */ out: return result; } tool_rc files_save_tpm_context_to_file(ESYS_CONTEXT *ectx, ESYS_TR handle, FILE *stream) { TPMS_CONTEXT *context = NULL; tool_rc rc = tpm2_context_save(ectx, handle, &context); if (rc != tool_rc_success) { return rc; } bool result = files_save_context(context, stream); free(context); return result ? tool_rc_success : tool_rc_general_error; } tool_rc files_save_tpm_context_to_path(ESYS_CONTEXT *context, ESYS_TR handle, const char *path) { FILE *f = fopen(path, "w+b"); if (!f) { LOG_ERR("Error opening file \"%s\" due to error: %s", path, strerror(errno)); return tool_rc_general_error; } tool_rc rc = files_save_tpm_context_to_file(context, handle, f); fclose(f); return rc; } static bool load_tpm_context_file(FILE *fstream, TPMS_CONTEXT *context) { /* * Reading the TPMS_CONTEXT structure to disk, format: * TPM2.0-TOOLS HEADER * U32 hierarchy * U32 savedHandle * U64 sequence * U16 contextBlobLength * BYTE[] contextBlob */ UINT32 version; bool result = files_read_header(fstream, &version); if (!result) { LOG_WARN("The loaded tpm context does not appear to be in the proper " "format, assuming old format, this will be converted on the " "next save."); rewind(fstream); result = files_read_bytes(fstream, (UINT8 *) context, sizeof(*context)); if (!result) { LOG_ERR("Could not load tpm context file"); goto out; } /* Success load the context into the TPM */ goto out; } if (version != CONTEXT_VERSION) { LOG_ERR("Unsupported context file format version found, got: %"PRIu32, version); result = false; goto out; } result = files_read_32(fstream, &context->hierarchy); if (!result) { LOG_ERR("Error reading hierarchy!"); goto out; } result = files_read_32(fstream, &context->savedHandle); if (!result) { LOG_ERR("Error reading savedHandle!"); goto out; } LOG_INFO("load: TPMS_CONTEXT->savedHandle: 0x%x", context->savedHandle); result = files_read_64(fstream, &context->sequence); if (!result) { LOG_ERR("Error reading sequence!"); goto out; } result = files_read_16(fstream, &context->contextBlob.size); if (!result) { LOG_ERR("Error reading contextBlob.size!"); goto out; } if (context->contextBlob.size > sizeof(context->contextBlob.buffer)) { LOG_ERR("Size mismatch found on contextBlob, got %"PRIu16" expected " "less than or equal to %zu", context->contextBlob.size, sizeof(context->contextBlob.buffer)); result = false; goto out; } result = files_read_bytes(fstream, context->contextBlob.buffer, context->contextBlob.size); if (!result) { LOG_ERR("Error reading contextBlob.size!"); goto out; } out: return result; } static bool check_magic(FILE *fstream, bool seek_reset) { BAIL_ON_NULL("FILE", fstream); UINT32 magic = 0; bool res = files_read_32(fstream, &magic); if (!res) { return false; } bool match = magic == MAGIC; if (seek_reset) { int rc = fseek(fstream, -sizeof(magic), SEEK_CUR); if (rc != 0) { LOG_ERR("fseek failed: %s", strerror(errno)); return false; } return match; } if (!match) { LOG_ERR("Found magic 0x%x did not match expected magic of 0x%x!", magic, MAGIC); } return match; } tool_rc files_load_tpm_context_from_file(ESYS_CONTEXT *context, ESYS_TR *tr_handle, FILE *fstream) { TPMS_CONTEXT tpms_context; tool_rc rc = tool_rc_general_error; bool result = check_magic(fstream, true); if (result) { LOG_INFO("Assuming tpm context file"); result = load_tpm_context_file(fstream, &tpms_context); if (!result) { LOG_ERR("Failed to load_tpm_context_file()"); goto out; } return tpm2_context_load(context, &tpms_context, tr_handle); } ESYS_TR loaded_handle; LOG_INFO("Assuming tpm context file"); /* try ESYS TR deserialize */ unsigned long size = 0; result = files_get_file_size(fstream, &size, NULL); if (!result) { LOG_ERR("Failed to get file size: %s", strerror(ferror(fstream))); goto out; } if (size < 1) { LOG_ERR("Invalid serialized ESYS_TR size, got: %lu", size); goto out; } uint8_t *buffer = calloc(1, size); if (!buffer) { LOG_ERR("oom"); goto out; } result = files_read_bytes(fstream, buffer, size); if (!result) { LOG_ERR("Could not read serialized ESYS_TR from disk"); free(buffer); goto out; } rc = tpm2_tr_deserialize(context, buffer, size, &loaded_handle); free(buffer); if (rc == tool_rc_success) { *tr_handle = loaded_handle; } out: return rc; } tool_rc files_load_tpm_context_from_path(ESYS_CONTEXT *context, ESYS_TR *tr_handle, const char *path) { FILE *f = fopen(path, "rb"); if (!f) { LOG_WARN("Error opening file \"%s\" due to error: %s", path, strerror(errno)); return false; } tool_rc rc = files_load_tpm_context_from_file(context, tr_handle, f); fclose(f); return rc; } bool files_does_file_exist(const char *path) { if (!path) { LOG_ERR("Path cannot be NULL"); return false; } FILE *fp = fopen(path, "rb"); if (fp) { fclose(fp); LOG_WARN("Path: %s already exists. Please rename or delete the file!", path); return true; } return false; } bool files_get_file_size_path(const char *path, unsigned long *file_size) { bool result = false; if (!path) { LOG_ERR("Must specify a path argument, cannot be NULL!"); return false; } if (!file_size) { LOG_ERR("Must specify a file size argument, cannot be NULL!"); return false; } FILE *fp = fopen(path, "rb"); if (!fp) { LOG_ERR("Could not open file: \"%s\" error: %s", path, strerror(errno)); return false; } result = files_get_file_size(fp, file_size, path); fclose(fp); return result; } #define BE_CONVERT(value, size) \ do { \ if (!tpm2_util_is_big_endian()) { \ value = tpm2_util_endian_swap_##size(value); \ } \ } while (0) #define FILE_WRITE(size) \ bool files_write_##size(FILE *out, UINT##size data) { \ BAIL_ON_NULL("FILE", out); \ BE_CONVERT(data, size); \ return writex(out, (UINT8 *)&data, sizeof(data)); \ } #define FILE_READ(size) \ bool files_read_##size(FILE *out, UINT##size *data) { \ BAIL_ON_NULL("FILE", out); \ BAIL_ON_NULL("data", data); \ bool res = (readx(out, (UINT8 *)data, sizeof(*data)) == sizeof(*data)); \ if (res) { \ BE_CONVERT(*data, size); \ } \ return res; \ } /* * all the files_read|write_bytes_16|32|64 functions */ FILE_READ(16); FILE_WRITE(16) FILE_READ(32); FILE_WRITE(32) FILE_READ(64) FILE_WRITE(64) bool files_read_bytes(FILE *out, UINT8 bytes[], size_t len) { BAIL_ON_NULL("FILE", out); BAIL_ON_NULL("bytes", bytes); return (readx(out, bytes, len) == len); } bool files_read_bytes_chunk(FILE *out, UINT8 bytes[], size_t len, size_t *read_len) { BAIL_ON_NULL("FILE", out); BAIL_ON_NULL("bytes", bytes); size_t chunk_len = readx(out, bytes, len); *read_len += chunk_len; return (chunk_len == len); } bool files_write_bytes(FILE *out, uint8_t bytes[], size_t len) { BAIL_ON_NULL("FILE", out); BAIL_ON_NULL("bytes", bytes); return writex(out, bytes, len); } bool files_write_header(FILE *out, UINT32 version) { BAIL_ON_NULL("FILE", out); bool res = files_write_32(out, MAGIC); if (!res) { return false; } return files_write_32(out, version); } bool files_read_header(FILE *out, uint32_t *version) { BAIL_ON_NULL("FILE", out); BAIL_ON_NULL("version", version); bool result = check_magic(out, false); if (!result) { return false; } return files_read_32(out, version); } bool files_load_bytes_from_buffer_or_file_or_stdin(const char *input_buffer, const char *path, UINT16 *size, BYTE *buf) { UINT16 upper_bound = *size; if (!upper_bound) { return true; } bool retval = true; /* Read from stdin */ if (!input_buffer && !path) { UINT16 read_bytes = 0; while (1) { read_bytes += fread(buf, 1, upper_bound, stdin); if (feof(stdin)) { *size = read_bytes; return true; } if (ferror(stdin)) { LOG_ERR("Failed read from stdin."); return false; } } /* read from a buffer */ } else if (input_buffer) { size_t input_buffer_size = strlen(input_buffer); if (path) { LOG_ERR("Specify either the input buffer or file path to load data," " not both"); } if (input_buffer_size != (size_t) upper_bound) { LOG_ERR("Unexpected data size. Got %u expected %u", upper_bound, (unsigned )input_buffer_size); return false; } else { memcpy(buf, input_buffer, input_buffer_size); return true; } } else if (path) { retval = files_load_bytes_from_path(path, buf, size); } return retval; } tool_rc files_save_ESYS_TR(ESYS_CONTEXT *ectx, ESYS_TR handle, const char *path) { size_t size; uint8_t *buffer; tool_rc rc = tpm2_tr_serialize(ectx, handle, &buffer, &size); if (rc != tool_rc_success) { return rc; } bool result = files_save_bytes_to_file(path, buffer, size); free(buffer); return result ? tool_rc_success : tool_rc_general_error; } #define SAVE_TYPE(type, name) \ bool files_save_##name(type *name, const char *path) { \ \ size_t offset = 0; \ UINT8 buffer[sizeof(*name)]; \ TSS2_RC rc = Tss2_MU_##type##_Marshal(name, buffer, sizeof(buffer), &offset); \ if (rc != TSS2_RC_SUCCESS) { \ LOG_ERR("Error serializing "str(name)" structure: 0x%x", rc); \ return false; \ } \ \ return files_save_bytes_to_file(path, buffer, offset); \ } #define LOAD_TYPE(type, name) \ bool files_load_##name(const char *path, type *name) { \ \ UINT8 buffer[sizeof(*name)]; \ UINT16 size = sizeof(buffer); \ bool res = files_load_bytes_from_path(path, buffer, &size); \ if (!res) { \ return false; \ } \ \ size_t offset = 0; \ TSS2_RC rc = Tss2_MU_##type##_Unmarshal(buffer, size, &offset, name); \ if (rc != TSS2_RC_SUCCESS) { \ LOG_ERR("Error deserializing "str(name)" structure: 0x%x", rc); \ LOG_ERR("The input file needs to be a valid "xstr(type)" data structure"); \ return false; \ } \ \ return rc == TPM2_RC_SUCCESS; \ } #define LOAD_TYPE_FILE(type, name) \ bool files_load_##name##_file(FILE *f, const char *path, type *name) { \ \ UINT8 buffer[sizeof(*name)]; \ UINT16 size = sizeof(buffer); \ bool res = file_read_bytes_from_file(f, buffer, &size, path); \ if (!res) { \ return false; \ } \ \ size_t offset = 0; \ TSS2_RC rc = Tss2_MU_##type##_Unmarshal(buffer, size, &offset, name); \ if (rc != TSS2_RC_SUCCESS) { \ LOG_ERR("Error deserializing "str(name)" structure: 0x%x", rc); \ LOG_ERR("The input file needs to be a valid "xstr(type)" data structure"); \ return false; \ } \ \ return rc == TPM2_RC_SUCCESS; \ } #define LOAD_TYPE_SILENT(type, name) \ bool files_load_##name##_silent(const char *path, type *name) { \ \ UINT8 buffer[sizeof(*name)]; \ UINT16 size = sizeof(buffer); \ bool res = files_load_bytes_from_path(path, buffer, &size); \ if (!res) { \ return false; \ } \ \ size_t offset = 0; \ TSS2_RC rc = Tss2_MU_##type##_Unmarshal(buffer, size, &offset, name); \ if (rc != TSS2_RC_SUCCESS) { \ return false; \ } \ \ return rc == TPM2_RC_SUCCESS; \ } SAVE_TYPE(TPM2B_PUBLIC, public) LOAD_TYPE(TPM2B_PUBLIC, public) LOAD_TYPE_FILE(TPM2B_PUBLIC, public) LOAD_TYPE_SILENT(TPM2B_PUBLIC, public) SAVE_TYPE(TPMT_PUBLIC, template) LOAD_TYPE(TPMT_PUBLIC, template) LOAD_TYPE_FILE(TPMT_PUBLIC, template) LOAD_TYPE_SILENT(TPMT_PUBLIC, template) SAVE_TYPE(TPMT_SIGNATURE, signature) LOAD_TYPE(TPMT_SIGNATURE, signature) LOAD_TYPE_SILENT(TPMT_SIGNATURE, signature) SAVE_TYPE(TPMT_TK_VERIFIED, ticket) LOAD_TYPE(TPMT_TK_VERIFIED, ticket) SAVE_TYPE(TPMT_TK_AUTH, authorization_ticket) LOAD_TYPE(TPMT_TK_AUTH, authorization_ticket) SAVE_TYPE(TPMT_TK_CREATION, creation_ticket) LOAD_TYPE(TPMT_TK_CREATION, creation_ticket) SAVE_TYPE(TPM2B_DIGEST, digest) LOAD_TYPE(TPM2B_DIGEST, digest) SAVE_TYPE(TPM2B_CREATION_DATA, creation_data) LOAD_TYPE(TPM2B_CREATION_DATA, creation_data) SAVE_TYPE(TPM2B_SENSITIVE, sensitive) LOAD_TYPE(TPM2B_SENSITIVE, sensitive) SAVE_TYPE(TPMT_TK_HASHCHECK, validation) LOAD_TYPE(TPMT_TK_HASHCHECK, validation) SAVE_TYPE(TPM2B_PRIVATE, private) LOAD_TYPE(TPM2B_PRIVATE, private) SAVE_TYPE(TPM2B_ENCRYPTED_SECRET, encrypted_seed) LOAD_TYPE(TPM2B_ENCRYPTED_SECRET, encrypted_seed) SAVE_TYPE(TPMS_ALGORITHM_DETAIL_ECC, ecc_details) SAVE_TYPE(TPM2B_ECC_POINT, ecc_point) LOAD_TYPE(TPM2B_ECC_POINT, ecc_point) LOAD_TYPE(TPM2B_ECC_PARAMETER, ecc_parameter) LOAD_TYPE_FILE(TPMS_ATTEST, attest) tool_rc files_tpm2b_attest_to_tpms_attest(TPM2B_ATTEST *quoted, TPMS_ATTEST *attest) { size_t offset = 0; TSS2_RC rval = Tss2_MU_TPMS_ATTEST_Unmarshal(quoted->attestationData, quoted->size, &offset, attest); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Tss2_MU_TPM2B_ATTEST_Unmarshal, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc files_load_unique_data(const char *file_path, TPM2B_PUBLIC *public_data) { /* * TPM2_MAX_RSA_KEY_BYTES which expands to 512 bytes is the maximum unique * size for RSA and other key types. * * Additionally this may still prove to be a bigger value than what has been * implemented in a TPM. For example the value of MAX_RSA_KEY_BYTES is 256 * for ibmSimulator as specified in implementation.h */ UINT16 unique_size = TPM2_MAX_RSA_KEY_BYTES; uint8_t file_data[TPM2_MAX_RSA_KEY_BYTES]; bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, file_path, &unique_size, file_data); if (!result) { LOG_ERR("Failed to load unique data from file/ stdin."); return tool_rc_general_error; } /* * If the data is specified as a file, the user is responsible for ensuring * that that this buffer is formatted as TPMU_PUBLIC_ID union. */ if (file_path) { memcpy(&public_data->publicArea.unique, file_data, unique_size); return tool_rc_success; } /* Unstructured stdin unique data paired with a RSA object */ if (public_data->publicArea.type == TPM2_ALG_RSA) { public_data->publicArea.unique.rsa.size = unique_size; memcpy(&public_data->publicArea.unique.rsa.buffer, file_data, unique_size); } /* Unstructured stdin unique data paired with an ECC object */ if (public_data->publicArea.type == TPM2_ALG_ECC) { /* The size limitation is TPM implementation dependent. */ if((unique_size / 2) > TPM2_MAX_ECC_KEY_BYTES) { LOG_ERR("Unique data too big for ECC object's allowed unique size"); return tool_rc_general_error; } /* Copy data into X and Y coordinates unique buffers */ public_data->publicArea.unique.ecc.x.size = (unique_size / 2); memcpy(&public_data->publicArea.unique.ecc.x.buffer, file_data, (unique_size / 2)); /* Copy the rest of buffer to y and also adjust size if input is odd */ public_data->publicArea.unique.ecc.y.size = (unique_size / 2) + (unique_size % 2); memcpy(&public_data->publicArea.unique.ecc.y.buffer, file_data + (unique_size / 2), (unique_size / 2)); } /* Unstructured stdin unique data paired with an Keyedhash object */ if (public_data->publicArea.type == TPM2_ALG_KEYEDHASH) { /* The size limitation is TPM implementation dependent. */ if (unique_size > sizeof(TPMU_HA)) { LOG_ERR("Unique data too big for keyedhash object's allowed unique " "size."); return tool_rc_general_error; } public_data->publicArea.unique.keyedHash.size = unique_size; memcpy(&public_data->publicArea.unique.keyedHash.buffer, file_data, unique_size); } /* Unstructured stdin unique data paired with an Symcipher object */ if (public_data->publicArea.type == TPM2_ALG_SYMCIPHER) { /* The size limitation is TPM implementation dependent. */ if (unique_size > sizeof(TPMU_HA)) { LOG_ERR("Unique data too big for TPM2_ALG_SYMCIPHER object's " "allowed unique size."); return tool_rc_general_error; } public_data->publicArea.unique.sym.size = unique_size; memcpy(&public_data->publicArea.unique.sym.buffer, file_data, unique_size); } return tool_rc_success; } tpm2-tools-5.2/lib/files.h000066400000000000000000000413261412464516500154370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef FILES_H #define FILES_H #include #include #include #include "tool_rc.h" /** * Reads a series of bytes from a file as a byte array. This is similar to files_read_bytes(), * but opens and closes the FILE for the caller. Size is both an input and output value where * the size value is the max buffer size on call and the returned size is how much was read. * * This interface could be cleaned up in a later revision. * @param path * The path to the file to open. * @param buf * The buffer to read the data into * @param size * The max size of the buffer on call, and the size of the data read on return. * @return * True on success, false otherwise. */ bool files_load_bytes_from_path(const char *path, UINT8 *buf, UINT16 *size); /** * Like files_load_bytes_from_path() but uses a FILE pointer. * @param f * The FILE pointer to read from. * @param buf * The buffer to store the data. * @param size * On input the max size of the buffer, on success the actual count of bytes read. * @param path * A possible path for error reporting, can be NULL to silence error reporting. * @return * True on success, false otherwise. */ bool file_read_bytes_from_file(FILE *f, UINT8 *buf, UINT16 *size, const char *path); /** * Loads data from an input buffer or file path or stdin enforcing an upper bound on size. * @param input_buffer * The buffer to read the input data from, NULL means either specified by path or stdin * @param path * The path to load data from, NULL means stdin. * @param size * The maximum size. * @param buf * The buffer to write the data into. * @return * True on success or false otherwise. */ bool files_load_bytes_from_buffer_or_file_or_stdin(const char *input_buffer, const char *path, UINT16 *size, BYTE *buf); /** * Similar to files_write_bytes(), in that it writes an array of bytes to disk, * but this routine opens and closes the file on the callers behalf. If the path * is NULL and silent output has not been enabled, then stdout is used. * @param path * The path to the file to write the data to. * @param buf * The buffer of data to write * @param size * The size of the data to write in bytes. * @return * True on success, false otherwise. */ bool files_save_bytes_to_file(const char *path, UINT8 *buf, UINT16 size); /** * Saves the TPM ESAPI context for an object handle to disk by calling * ContextSave() and serializing the resulting TPMS_CONTEXT structure * to disk. * @param context * The Enhances System API (ESAPI) context * @param handle * The object handle for the object to save. * @param path * The output path of the file. * * @return * tool_rc indicating status. */ tool_rc files_save_tpm_context_to_path(ESYS_CONTEXT *context, ESYS_TR handle, const char *path); /** * Like files_save_tpm_context_to_path() but saves a tpm session to a FILE stream. * @param context * The Enhances System API (ESAPI) context * @param handle * The object handle for the object to save. * @param stream * The FILE stream to save too. * @return * tool_rc indicating status. */ tool_rc files_save_tpm_context_to_file(ESYS_CONTEXT *context, ESYS_TR handle, FILE *stream); /** * Loads a ESAPI TPM object context from disk or an ESAPI serialized ESYS_TR object. * @param context * The Enhanced System API (ESAPI) context * @param tr_handle * Optional. The Esys handle for the TPM2 object. * @param path * The path to the input file. * @return * tool_rc status indicating success. */ tool_rc files_load_tpm_context_from_path(ESYS_CONTEXT *context, ESYS_TR *tr_handle, const char *path); /** * Like files_load_tpm_context_from_path() but loads the context from a FILE stream. * @param context * The Enhanced System API (ESAPI) context * @param tr_handle * Optional. The Esys handle for the TPM2 object * @param stream * The FILE stream to read from. * @return * tool_rc status indicating success. */ tool_rc files_load_tpm_context_from_file(ESYS_CONTEXT *context, ESYS_TR *tr_handle, FILE *stream); /** * Save an ESYS_TR to disk. * @param ectx * The ESAPI context * @param handle * The handle to serialize. * @param path * The path to save to. * @return * A tool_rc indicating status. */ tool_rc files_save_ESYS_TR(ESYS_CONTEXT *ectx, ESYS_TR handle, const char *path); /** * Serializes a TPM2B_PUBLIC to the file path provided. * @param public * The TPM2B_PUBLIC to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_public(TPM2B_PUBLIC *public, const char *path); /** * Serializes a TPMT_PUBLIC to the file path provided. * @param template * The TPMT_PUBLIC to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_template(TPMT_PUBLIC *template, const char *path); /** * Like files_load_template(), but doesn't report errors. * @param path * The path containing the TPMT_PUBLIC to load from. * @param public * The destination for the TPMT_PUBLIC. * @return * true on success, false otherwise. */ bool files_load_template_silent(const char *path, TPMT_PUBLIC *public); /** * Loads a TPM2B_PUBLIC from disk that was saved with files_save_pubkey() * @param path * The path to load from. * @param public * The TPM2B_PUBLIC to load. * @return * true on success, false on error. */ bool files_load_public(const char *path, TPM2B_PUBLIC *public); /** * Like files_load_public(), but doesn't report errors. * @param path * The path containing the TP2B_PUBLIC to load from. * @param public * The destination for the TP2B_PUBLIC. * @return * true on success, false otherwise. */ bool files_load_public_file(FILE *f, const char *path, TPM2B_PUBLIC *public); bool files_load_template(const char *path, TPMT_PUBLIC *public); bool files_load_template_file(FILE *f, const char *path, TPMT_PUBLIC *public); /** * Like files_load_public(), but doesn't report errors. * @param path * The path containing the TP2B_PUBLIC to load from. * @param public * The destination for the TP2B_PUBLIC. * @return * true on success, false otherwise. */ bool files_load_public_silent(const char *path, TPM2B_PUBLIC *public); /** * Serializes a TPMT_SIGNATURE to the file path provided. * @param signature * The TPMT_SIGNATURE to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_signature(TPMT_SIGNATURE *signature, const char *path); /** * Loads a TPMT_SIGNATURE from disk that was saved with files_save_signature() * @param path * The path to load from. * @param signature * The TPMT_SIGNATURE to load. * @return * true on success, false on error. */ bool files_load_signature(const char *path, TPMT_SIGNATURE *signature); /** * Like files_save)signature() but doesn't complain about libmu failures. * Useful if you're trying to probe if its a plain or tss format signature. * @param path * The path to load from. * @param signature * The TPMT_SIGNATURE to load. * @return * true on success, false on error. */ bool files_load_signature_silent(const char *path, TPMT_SIGNATURE *signature); /** * Serializes a TPMT_TK_VERIFIED to the file path provided. * @param signature * The TPMT_SIGNATURE to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_ticket(TPMT_TK_VERIFIED *ticket, const char *path); /** * Loads a TPMT_TK_VERIFIED from disk that was saved with files_save_ticket() * @param path * The path to load from. * @param signature * The TPMT_TK_VERIFIED to load. * @return * true on success, false on error. */ bool files_load_ticket(const char *path, TPMT_TK_VERIFIED *ticket); /** * Serializes a TPMT_TK_AUTH to the file path provided. * @param signature * The TPMT_SIGNATURE to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_authorization_ticket(TPMT_TK_AUTH *authorization_ticket, const char *path); /** * Loads a TPMT_TK_AUTH from disk that was saved with * files_save_authorization_ticket() * @param path * The path to load from. * @param signature * The TPMT_TK_AUTH to load. * @return * true on success, false on error. */ bool files_load_authorization_ticket(const char *path, TPMT_TK_AUTH *authorization_ticket); bool files_load_creation_data(const char *path, TPM2B_CREATION_DATA *creation_data); bool files_save_creation_data(TPM2B_CREATION_DATA *creation_data, const char *path); bool files_load_creation_ticket(const char *path, TPMT_TK_CREATION *creation_ticket); bool files_save_creation_ticket(TPMT_TK_CREATION *creation_ticket, const char *path); bool files_load_digest(const char *path, TPM2B_DIGEST *digest); bool files_save_digest(TPM2B_DIGEST *digest, const char *path); /** * Loads a TPM2B_SENSITIVE from disk. * @param path * The path to load from. * @param signature * The TPM2B_SENSITIVE to load. * @return * true on success, false on error. */ bool files_load_sensitive(const char *path, TPM2B_SENSITIVE *sensitive); /** * Serializes a TPM2B_SENSITIVE to the file path provided. * @param sensitive * The TPM2B_SENSITIVE to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_sensitive(TPM2B_SENSITIVE *sensitive, const char *path); /** * Serializes a TPMT_TK_HASHCHECK to the file path provided. * @param validation * The TPMT_TK_HASHCHECK to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_validation(TPMT_TK_HASHCHECK *validation, const char *path); /** * Loads a TPMT_TK_HASHCHECK from disk. * @param path * The path to load from. * @param validation * The TPMT_TK_HASHCHECK to load. * @return * true on success, false on error. */ bool files_load_validation(const char *path, TPMT_TK_HASHCHECK *validation); /** * Serializes a TPM2B_PRIVATE to the file path provided. * @param private * The TPM2B_PRIVATE to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_private(TPM2B_PRIVATE *private, const char *path); /** * Loads a TPM2B_PRIVATE from disk. * @param private * The path to load from. * @param validation * The TPM2B_PRIVATE to load. * @return * true on success, false on error. */ bool files_load_private(const char *path, TPM2B_PRIVATE *private); /** * Serializes a TPM2B_ENCRYPTED_SECRET to the file path provided. * @param encrypted_seed * The TPM2B_ENCRYPTED_SECRET to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_encrypted_seed(TPM2B_ENCRYPTED_SECRET *encrypted_seed, const char *path); /** * Serializes a TPM2B_ECC_POINT to the file path provided. * @param Q * The TPM2B_ECC_POINT to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_ecc_point(TPM2B_ECC_POINT *Q, const char *path); /** * Loads a TPM2B_ECC_POINT from disk. * @param path * The path to load from. * @param Q * The TPM2B_ECC_POINT data to load. */ bool files_load_ecc_point(const char *path, TPM2B_ECC_POINT *Q); /** * Loads a TPM2B_ECC_PARAMETER from disk * @param path * The path to load from. * @param parameter * The TPM2B_ECC_PARAMETER data to load. */ bool files_load_ecc_parameter(const char *path, TPM2B_ECC_PARAMETER *parameter); /** * Loads a TPM2B_ENCRYPTED_SECRET from disk. * @param encrypted_seed * The path to load from. * @param validation * The TPM2B_ENCRYPTED_SECRET to load. * @return * true on success, false on error. */ bool files_load_encrypted_seed(const char *path, TPM2B_ENCRYPTED_SECRET *encrypted_seed); /** * Serializes a TPMS_ALGORITHM_DETAIL_ECC to the file path provided. * @param parameters * The TPMS_ALGORITHM_DETAIL_ECC to save to disk. * @param path * The path to save to. * @return * true on success, false on error. */ bool files_save_ecc_details(TPMS_ALGORITHM_DETAIL_ECC *parameters, const char *path); /** * Checks a file for existence. * @param path * The file to check for existence. * @return * true if a file exists with read permissions, false if it doesn't exist or an error occurs. * */ bool files_does_file_exist(const char *path); /** * Retrieves a files size given a file path. * @param path * The path of the file to retrieve the size of. * @param file_size * A pointer to an unsigned long to return the file size. The * pointed to value is valid only on a true return. * * @return * True for success or False for error. */ bool files_get_file_size_path(const char *path, unsigned long *file_size); /** * Similar to files_get_file_size_path(), but uses an already opened FILE object. * @param fp * The file pointer to query the size of. * @param file_size * Output of the file size. * @param path * An optional path used for error reporting, a NULL path disables error logging. * @return * True on success, False otherwise. */ bool files_get_file_size(FILE *fp, unsigned long *file_size, const char *path); /** * Writes a TPM2.0 header to a file. * @param f * The file to write to. * @param version * The version number of the format of the file. * @return * True on success, false on error. */ bool files_write_header(FILE *f, UINT32 version); /** * Reads a TPM2.0 header from a file. * @param f * The file to read. * @param version * The version that was found. * @return * True on Success, False on error. */ bool files_read_header(FILE *f, UINT32 *version); /** * Writes a 16 bit value to the file in big endian, converting * if needed. * @param out * The file to write. * @param data * The 16 bit value to write. * @return * True on success, False on error. */ bool files_write_16(FILE *out, UINT16 data); /** * Same as files_write_16 but for 32 bit values. */ bool files_write_32(FILE *out, UINT32 data); /** * Same as files_write_16 but for 64 bit values. */ bool files_write_64(FILE *out, UINT64 data); /** * Writes a byte array out to a file. * @param out * The file to write to. * @param data * The data to write. * @param size * The size of the data to write in bytes. * @return * True on success, False otherwise. */ bool files_write_bytes(FILE *out, UINT8 data[], size_t size); /** * Reads a 16 bit value from a file converting from big endian to host * endianess. * @param out * The file to read from. * @param data * The data that is read, valid on a true return. * @return * True on success, False on error. */ bool files_read_16(FILE *out, UINT16 *data); /** * Same as files_read_16 but for 32 bit values. */ bool files_read_32(FILE *out, UINT32 *data); /** * Same as files_read_16 but for 64 bit values. */ bool files_read_64(FILE *out, UINT64 *data); /** * Reads len bytes from a file. * @param out * The file to read from. * @param data * The buffer to read into, only valid on a True return. * @param size * The number of bytes to read. * @return * True on success, False otherwise. */ bool files_read_bytes(FILE *out, UINT8 data[], size_t size); /** * Reads len bytes from a file and set the read length. * @param out * The file to read from. * @param data * The buffer to read into, only valid on a True return. * @param size * The number of bytes to read. * @param read_size * Total number of bytes read. * @return * True on success, False otherwise. */ bool files_read_bytes_chunk(FILE *out, UINT8 data[], size_t size, size_t *read_size); /** * Converts a TPM2B_ATTEST to a TPMS_ATTEST using libmu. * @param quoted * The attestation quote structure. * @param attest * The TPMS_ATTEST to populate. * @return * tool_rc_success on success, false otherwise. */ tool_rc files_tpm2b_attest_to_tpms_attest(TPM2B_ATTEST *quoted, TPMS_ATTEST *attest); /** * Loads a TPMS_ATTEST from disk. * @param f * The file to load. * @param path * The path to load from. * @param attest * The attest structure to fill up. * @return * True on success, false otherwise. */ bool files_load_attest_file(FILE *f, const char *path, TPMS_ATTEST *attest); /** * @brief * Parse the key type and load the unique data in the object's * TPM2B_PUBLIC area. * * @param file_path * The file to read the unique data from. This can be NULL to indicate stdin * @param public_data * The TPM2B public structure to parse the object type and also to update the * unique data as read from the file or stdin. * * @return * tool_rc type signaling the status at the end of read attempt. * */ tool_rc files_load_unique_data(const char *file_path, TPM2B_PUBLIC *public_data); #endif /* FILES_H */ tpm2-tools-5.2/lib/log.c000066400000000000000000000026221412464516500151050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "log.h" /* * Note that the logging library is not thread safe, thus calls on separate * threads will yield an interleaved output on stderr. */ static log_level current_log_level = log_level_warning; void log_set_level(log_level value) { current_log_level = value; } static const char * get_level_msg(log_level level) { const char *value = "UNK"; switch (level) { case log_level_error: value = "ERROR"; break; case log_level_warning: value = "WARN"; break; case log_level_verbose: value = "INFO"; } return value; } void _log(log_level level, const char *file, unsigned lineno, const char *fmt, ...) { /* Skip printing messages outside of the log level */ if (level > current_log_level) return; va_list argptr; va_start(argptr, fmt); /* Verbose output prints file and line on error */ if (current_log_level >= log_level_verbose) { fprintf(stderr, "%s on line: \"%u\" in file: \"%s\": ", get_level_msg(level), lineno, file); } else { fprintf(stderr, "%s: ", get_level_msg(level)); } /* Print the user supplied message */ vfprintf(stderr, fmt, argptr); /* always add a new line so the user doesn't have to */ fprintf(stderr, "\n"); va_end(argptr); } tpm2-tools-5.2/lib/log.h000066400000000000000000000040411412464516500151070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_LOG_H_ #define SRC_LOG_H_ #include #include #include #include #include "tpm2_util.h" typedef enum log_level log_level; enum log_level { log_level_error, log_level_warning, log_level_verbose }; void _log (log_level level, const char *file, unsigned lineno, const char *fmt, ...) COMPILER_ATTR(format (printf, 4, 5)); /* * Prints an error message. The fmt and variadic arguments mirror printf. * * Use this to log all error conditions. */ #define LOG_ERR(fmt, ...) _log(log_level_error, __FILE__, __LINE__, fmt, ##__VA_ARGS__) /** * Prints an error message for a TSS2_Sys call to the TPM. * The format is (0x) - * @param func * The function that caused the error * @param rc * The return code to print. */ #define LOG_PERR(func, rc) _LOG_PERR(xstr(func), rc) /** * Internal use only. * * Handles the expanded LOG_PERR call checking argument values * and handing them off to LOG_ERR. * @param func * The function name. * @param rc * The rc to decode. */ static inline void _LOG_PERR(const char *func, TSS2_RC rc) { LOG_ERR("%s(0x%X) - %s", func, rc, Tss2_RC_Decode(rc)); } /* * Prints an warning message. The fmt and variadic arguments mirror printf. * * Use this to log a warning. A warning is when something is wrong, but it is not a fatal * issue. */ #define LOG_WARN(fmt, ...) _log(log_level_warning, __FILE__, __LINE__, fmt, ##__VA_ARGS__) /* * Prints an informational message. The fmt and variadic arguments mirror printf. * * Informational messages are only shown when verboseness is increased. Valid messages * would be debugging type messages where additional, extraneous information is printed. */ #define LOG_INFO(fmt, ...) _log(log_level_verbose, __FILE__, __LINE__, fmt, ##__VA_ARGS__) /** * Sets the log level so only messages <= to it print. * @param level * The logging level to set. */ void log_set_level(log_level level); #endif /* SRC_LOG_H_ */ tpm2-tools-5.2/lib/object.c000066400000000000000000000045741412464516500156020ustar00rootroot00000000000000 #include #include "files.h" #include "log.h" #include "object.h" #include "tool_rc.h" #include "tpm2_auth_util.h" #define NULL_OBJECT "null" #define NULL_OBJECT_LEN (sizeof(NULL_OBJECT) - 1) static tool_rc do_ctx_file(ESYS_CONTEXT *ctx, const char *objectstr, FILE *f, tpm2_loaded_object *outobject) { /* assign a dummy transient handle */ outobject->handle = TPM2_TRANSIENT_FIRST; outobject->path = objectstr; return files_load_tpm_context_from_file(ctx, &outobject->tr_handle, f); } static tool_rc tpm2_util_object_load2(ESYS_CONTEXT *ctx, const char *objectstr, const char *auth, bool do_auth, tpm2_loaded_object *outobject, bool is_restricted_pswd_session, tpm2_handle_flags flags) { ESYS_CONTEXT *tmp_ctx = is_restricted_pswd_session ? NULL : ctx; if (do_auth) { tpm2_session *s = NULL; tool_rc rc = tpm2_auth_util_from_optarg(tmp_ctx, auth, &s, is_restricted_pswd_session); if (rc != tool_rc_success) { return rc; } outobject->session = s; } if (!objectstr) { LOG_ERR("object string is empty"); return tool_rc_general_error; } // 1. Always attempt file FILE *f = fopen(objectstr, "rb"); if (f) { tool_rc rc = do_ctx_file(ctx, objectstr, f, outobject); fclose(f); return rc; } // 2. Try to convert a hierarchy or raw handle TPMI_RH_PROVISION handle; bool result = tpm2_util_handle_from_optarg(objectstr, &handle, flags); if (result) { outobject->handle = handle; outobject->path = NULL; return tpm2_util_sys_handle_to_esys_handle(ctx, outobject->handle, &outobject->tr_handle); } LOG_ERR("Cannot make sense of object context \"%s\"", objectstr); return tool_rc_general_error; } tool_rc tpm2_util_object_load(ESYS_CONTEXT *ctx, const char *objectstr, tpm2_loaded_object *outobject, tpm2_handle_flags flags) { return tpm2_util_object_load2(ctx, objectstr, NULL, false, outobject, false, flags); } tool_rc tpm2_util_object_load_auth(ESYS_CONTEXT *ctx, const char *objectstr, const char *auth, tpm2_loaded_object *outobject, bool is_restricted_pswd_session, tpm2_handle_flags flags) { return tpm2_util_object_load2(ctx, objectstr, auth, true, outobject, is_restricted_pswd_session, flags); } tpm2-tools-5.2/lib/object.h000066400000000000000000000041141412464516500155750ustar00rootroot00000000000000#ifndef LIB_OBJECT_H_ #define LIB_OBJECT_H_ #include "tool_rc.h" #include "tpm2_session.h" #include "tpm2_util.h" typedef struct tpm2_loaded_object tpm2_loaded_object; struct tpm2_loaded_object { TPM2_HANDLE handle; ESYS_TR tr_handle; const char *path; tpm2_session *session; }; /** * Parses a string representation of a context object, either a file or handle, * and loads the context object ensuring the handle member of the out object is * set. * The objectstr will recognised as a context file when prefixed with "file:" * or should the value not be parsable as a handle number (as understood by * strtoul()). * @param ctx * a TSS ESAPI context. * @param objectstr * The string representation of the object to be loaded. * @param outobject * A *tpm2_loaded_object* with a loaded handle. The path member will also be * set when the *objectstr* is a context file. * @param flags * A *tpm2_hierarchy_flags* value to specify expected valid hierarchy * @return * tool_rc indicating status. * */ tool_rc tpm2_util_object_load(ESYS_CONTEXT *ctx, const char *objectstr, tpm2_loaded_object *outobject, tpm2_handle_flags flags); /** * Same as tpm2_util_object_load but allows the auth string value to be populated * as a session associated with the object. * @param ctx * a TSS ESAPI context. * @param objectstr * The string representation of the object to be loaded. * @param auth * The auth string for the object. * @param is_restricted_pswd_session * The auth session associated with the object is restricted to TPM2_RS_PW * @param outobject * A *tpm2_loaded_object* with a loaded handle. The path member will also be * set when the *objectstr* is a context file. * @param flags * A *tpm2_hierarchy_flags* value to specify expected valid hierarchy * @return * tool_rc indicating status. * @return * tool_rc indicating status */ tool_rc tpm2_util_object_load_auth(ESYS_CONTEXT *ctx, const char *objectstr, const char *auth, tpm2_loaded_object *outobject, bool is_restricted_pswd_session, tpm2_handle_flags flags); #endif /* LIB_OBJECT_H_ */ tpm2-tools-5.2/lib/pcr.c000066400000000000000000000431421412464516500151120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_systemdeps.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_util.h" #define MAX(a,b) ((a>b)?a:b) static inline void set_pcr_select_size(TPMS_PCR_SELECTION *pcr_selection, UINT8 size) { pcr_selection->sizeofSelect = size; } bool pcr_get_id(const char *arg, UINT32 *pcr_id) { if (arg == NULL || pcr_id == NULL) { LOG_ERR("arg or pcr_id is NULL"); return false; } return tpm2_util_handle_from_optarg(arg, pcr_id, TPM2_HANDLE_FLAGS_PCR); } static bool pcr_parse_list(const char *str, size_t len, TPMS_PCR_SELECTION *pcr_select) { char buf[4]; const char *current_string; int current_length; UINT32 pcr; if (str == NULL || len == 0 || strlen(str) == 0) { return false; } pcr_select->sizeofSelect = 3; pcr_select->pcrSelect[0] = 0; pcr_select->pcrSelect[1] = 0; pcr_select->pcrSelect[2] = 0; if (!strncmp(str, "all", 3)) { pcr_select->pcrSelect[0] = 0xff; pcr_select->pcrSelect[1] = 0xff; pcr_select->pcrSelect[2] = 0xff; return true; } if (!strncmp(str, "none", 4)) { pcr_select->pcrSelect[0] = 0x00; pcr_select->pcrSelect[1] = 0x00; pcr_select->pcrSelect[2] = 0x00; return true; } do { current_string = str; str = memchr(current_string, ',', len); if (str) { current_length = str - current_string; str++; len -= current_length + 1; } else { current_length = len; len = 0; } if ((size_t) current_length > sizeof(buf) - 1) { return false; } snprintf(buf, current_length + 1, "%s", current_string); if (!pcr_get_id(buf, &pcr)) { return false; } pcr_select->pcrSelect[pcr / 8] |= (1 << (pcr % 8)); } while (str); return true; } static bool pcr_parse_selection(const char *str, size_t len, TPMS_PCR_SELECTION *pcr_select) { const char *left_string; char buf[9]; if (str == NULL || len == 0 || strlen(str) == 0) return false; left_string = memchr(str, ':', len); if (left_string == NULL) { return false; } if ((size_t) (left_string - str) > sizeof(buf) - 1) { return false; } snprintf(buf, left_string - str + 1, "%s", str); pcr_select->hash = tpm2_alg_util_from_optarg(buf, tpm2_alg_util_flags_hash); if (pcr_select->hash == TPM2_ALG_ERROR) { return false; } left_string++; if ((size_t) (left_string - str) >= len) { return false; } if (!pcr_parse_list(left_string, str + len - left_string, pcr_select)) { return false; } return true; } static void shrink_pcr_selection(TPML_PCR_SELECTION *s) { UINT32 i, j; //seek for the first empty item for (i = 0; i < s->count; i++) if (!s->pcrSelections[i].hash) break; j = i + 1; for (; i < s->count; i++) { if (!s->pcrSelections[i].hash) { for (; j < s->count; j++) if (s->pcrSelections[j].hash) break; if (j >= s->count) break; memcpy(&s->pcrSelections[i], &s->pcrSelections[j], sizeof(s->pcrSelections[i])); s->pcrSelections[j].hash = 0; j++; } } s->count = i; } static void pcr_update_pcr_selections(TPML_PCR_SELECTION *s1, TPML_PCR_SELECTION *s2) { UINT32 i1, i2, j; for (i2 = 0; i2 < s2->count; i2++) { for (i1 = 0; i1 < s1->count; i1++) { if (s2->pcrSelections[i2].hash != s1->pcrSelections[i1].hash) continue; for (j = 0; j < s1->pcrSelections[i1].sizeofSelect; j++) s1->pcrSelections[i1].pcrSelect[j] &= ~s2->pcrSelections[i2].pcrSelect[j]; } } } static bool pcr_unset_pcr_sections(TPML_PCR_SELECTION *s) { UINT32 i, j; for (i = 0; i < s->count; i++) { for (j = 0; j < s->pcrSelections[i].sizeofSelect; j++) { if (s->pcrSelections[i].pcrSelect[j]) { return false; } } } return true; } bool pcr_print_pcr_struct_le(TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { UINT32 vi = 0, di = 0, i; bool result = true; tpm2_tool_output("pcrs:\n"); /* Loop through all PCR/hash banks */ for (i = 0; i < le32toh(pcr_select->count); i++) { const char *alg_name = tpm2_alg_util_algtostr( le16toh(pcr_select->pcrSelections[i].hash), tpm2_alg_util_flags_hash); tpm2_tool_output(" %s:\n", alg_name); /* Loop through all PCRs in this bank */ unsigned int pcr_id; for (pcr_id = 0; pcr_id < pcr_select->pcrSelections[i].sizeofSelect * 8u; pcr_id++) { if (!tpm2_util_is_pcr_select_bit_set(&pcr_select->pcrSelections[i], pcr_id)) { continue; // skip non-selected banks } if (vi >= le64toh(pcrs->count) || di >= le32toh(pcrs->pcr_values[vi].count)) { LOG_ERR("Something wrong, trying to print but nothing more"); return false; } /* Print out PCR ID */ tpm2_tool_output(" %-2d: 0x", pcr_id); /* Print out current PCR digest value */ TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di]; int k; for (k = 0; k < le16toh(b->size); k++) { tpm2_tool_output("%02X", b->buffer[k]); } tpm2_tool_output("\n"); if (++di < le32toh(pcrs->pcr_values[vi].count)) { continue; } di = 0; if (++vi < le64toh(pcrs->count)) { continue; } } } return result; } bool pcr_fwrite_serialized(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *ppcrs, FILE *output_file) { TPML_PCR_SELECTION pcr_selection = *pcr_select; for (UINT32 i = 0; i < pcr_selection.count; i++) { TPMS_PCR_SELECTION *p = &pcr_selection.pcrSelections[i]; p->hash = htole16(p->hash); } pcr_selection.count = htole32(pcr_selection.count); // Export TPML_PCR_SELECTION structure to pcr outfile size_t fwrite_len = fwrite(&pcr_selection, sizeof(TPML_PCR_SELECTION), 1, output_file); if (fwrite_len != 1) { LOG_ERR("write to output file failed: %s", strerror(errno)); return false; } // Export PCR digests to pcr outfile UINT32 count = htole32(ppcrs->count); fwrite_len = fwrite(&count, sizeof(UINT32), 1, output_file); if (fwrite_len != 1) { LOG_ERR("write to output file failed: %s", strerror(errno)); return false; } tpm2_pcrs pcrs = *ppcrs; for (size_t j = 0; j < pcrs.count; j++) { TPML_DIGEST *pcr_value = &pcrs.pcr_values[j]; for (size_t k = 0; k < pcr_value->count; k++) { TPM2B_DIGEST *p = &pcr_value->digests[k]; p->size = htole16(p->size); } pcr_value->count = htole32(pcr_value->count); fwrite_len = fwrite(pcr_value, sizeof(TPML_DIGEST), 1, output_file); if (fwrite_len != 1) { LOG_ERR("write to output file failed: %s", strerror(errno)); return false; } } return true; } bool pcr_fwrite_values(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *pcrs, FILE *output_file) { size_t vi = 0; /* value index */ UINT32 di = 0; /* digest index */ // Loop through all PCR/hash banks for (UINT32 i = 0; i < pcr_select->count; i++) { const TPMS_PCR_SELECTION *pcr_selection = &pcr_select->pcrSelections[i]; // Loop through all PCRs in this bank for (unsigned int pcr_id = 0; pcr_id < pcr_selection->sizeofSelect * 8u; pcr_id++) { bool is_pcr_select_bit_set = tpm2_util_is_pcr_select_bit_set( pcr_selection, pcr_id); if (! is_pcr_select_bit_set) { // skip non-selected banks continue; } const TPML_DIGEST *pcr_value = &pcrs->pcr_values[vi]; if (vi >= pcrs->count || di >= pcr_value->count) { LOG_ERR("Something wrong, trying to print but nothing more"); return false; } // Print out current PCR digest value const TPM2B_DIGEST *digest = &pcr_value->digests[di]; size_t fwrite_len = fwrite(digest->buffer, digest->size, 1, output_file); if (fwrite_len != 1) { LOG_ERR("write to output file failed: %s", strerror(errno)); return false; } if (++di >= pcr_value->count) { di = 0; ++vi; } } /* end looping through all PCRs in a bank */ } /* end looping through all PCR banks */ return true; } bool pcr_print_values(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *pcrs) { size_t vi = 0; /* value index */ UINT32 di = 0; /* digest index */ // Loop through all PCR/hash banks for (UINT32 i = 0; i < pcr_select->count; i++) { const TPMS_PCR_SELECTION *pcr_selection = &pcr_select->pcrSelections[i]; const char *alg_name = tpm2_alg_util_algtostr(pcr_selection->hash, tpm2_alg_util_flags_hash); tpm2_tool_output(" %s:\n", alg_name); // Loop through all PCRs in this bank for (unsigned int pcr_id = 0; pcr_id < pcr_selection->sizeofSelect * 8u; pcr_id++) { bool is_pcr_select_bit_set = tpm2_util_is_pcr_select_bit_set( pcr_selection, pcr_id); if (! is_pcr_select_bit_set) { // skip non-selected banks continue; } const TPML_DIGEST *pcr_value = &pcrs->pcr_values[vi]; if (vi >= pcrs->count || di >= pcr_value->count) { LOG_ERR("Something wrong, trying to print but nothing more"); return false; } // Print out PCR ID tpm2_tool_output(" %-2d: 0x", pcr_id); // Print out current PCR digest value const TPM2B_DIGEST *digest = &pcr_value->digests[di]; for (int k = 0; k < digest->size; k++) { tpm2_tool_output("%02X", digest->buffer[k]); } tpm2_tool_output("\n"); if (++di >= pcr_value->count) { di = 0; ++vi; } } /* end looping through all PCRs in a bank */ } /* end looping through all PCR banks */ return true; } bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { tpm2_tool_output("pcrs:\n"); return pcr_print_values(pcr_select, pcrs); } bool pcr_print_pcr_selections(TPML_PCR_SELECTION *pcr_selections) { tpm2_tool_output("selected-pcrs:\n"); /* Iterate throught the pcr banks */ UINT32 i; for (i = 0; i < pcr_selections->count; i++) { /* Print hash alg of the current bank */ const char *halgstr = tpm2_alg_util_algtostr( pcr_selections->pcrSelections[i].hash, tpm2_alg_util_flags_hash); if (halgstr != NULL) { tpm2_tool_output(" - %s: [", halgstr); } else { LOG_ERR("Unsupported hash algorithm 0x%08x", pcr_selections->pcrSelections[i].hash); return false; } /* Iterate through the PCRs of the bank */ bool first = true; unsigned j; for (j = 0; j < pcr_selections->pcrSelections[i].sizeofSelect * 8; j++) { if ((pcr_selections->pcrSelections[i].pcrSelect[j / 8] & 1 << (j % 8)) != 0) { if (first) { tpm2_tool_output(" %i", j); first = false; } else { tpm2_tool_output(", %i", j); } } } tpm2_tool_output(" ]\n"); } return true; } bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcr_select) { const char *left_string = arg; const char *current_string = arg; int current_length = 0; if (arg == NULL || pcr_select == NULL) { return false; } pcr_select->count = 0; do { current_string = left_string; left_string = strchr(current_string, '+'); if (left_string) { current_length = left_string - current_string; left_string++; } else current_length = strlen(current_string); if (!pcr_parse_selection(current_string, current_length, &pcr_select->pcrSelections[pcr_select->count])) return false; pcr_select->count++; } while (left_string); if (pcr_select->count == 0) { return false; } return true; } tool_rc pcr_get_banks(ESYS_CONTEXT *esys_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs) { TPMI_YES_NO more_data; TPMS_CAPABILITY_DATA *capdata_ret; tool_rc rc = tpm2_get_capability(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_PCRS, no_argument, required_argument, &more_data, &capdata_ret); if (rc != tool_rc_success) { return rc; } *capability_data = *capdata_ret; unsigned i; // If the TPM support more bank algorithm that we currently // able to manage, throw an error if (capability_data->data.assignedPCR.count > ARRAY_LEN(algs->alg)) { LOG_ERR("Current implementation does not support more than %zu banks, " "got %" PRIu32 " banks supported by TPM", sizeof(algs->alg), capability_data->data.assignedPCR.count); free(capdata_ret); return tool_rc_general_error; } for (i = 0; i < capability_data->data.assignedPCR.count; i++) { algs->alg[i] = capability_data->data.assignedPCR.pcrSelections[i].hash; } algs->count = capability_data->data.assignedPCR.count; free(capdata_ret); return tool_rc_success; } bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel, TPMI_ALG_HASH alg_id) { UINT32 i, j; pcr_sel->count = 0; for (i = 0; i < cap_data->data.assignedPCR.count; i++) { if (alg_id && (cap_data->data.assignedPCR.pcrSelections[i].hash != alg_id)) continue; pcr_sel->pcrSelections[pcr_sel->count].hash = cap_data->data.assignedPCR.pcrSelections[i].hash; set_pcr_select_size(&pcr_sel->pcrSelections[pcr_sel->count], cap_data->data.assignedPCR.pcrSelections[i].sizeofSelect); for (j = 0; j < pcr_sel->pcrSelections[pcr_sel->count].sizeofSelect; j++) pcr_sel->pcrSelections[pcr_sel->count].pcrSelect[j] = cap_data->data.assignedPCR.pcrSelections[i].pcrSelect[j]; pcr_sel->count++; } if (pcr_sel->count == 0) return false; return true; } bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_sel) { UINT32 i, j, k; for (i = 0; i < pcr_sel->count; i++) { for (j = 0; j < cap_data->data.assignedPCR.count; j++) { if (pcr_sel->pcrSelections[i].hash == cap_data->data.assignedPCR.pcrSelections[j].hash) { for (k = 0; k < pcr_sel->pcrSelections[i].sizeofSelect; k++) pcr_sel->pcrSelections[i].pcrSelect[k] &= cap_data->data.assignedPCR.pcrSelections[j].pcrSelect[k]; break; } } if (j >= cap_data->data.assignedPCR.count) { const char *alg_name = tpm2_alg_util_algtostr( pcr_sel->pcrSelections[i].hash, tpm2_alg_util_flags_hash); LOG_WARN("Ignore unsupported bank/algorithm: %s(0x%04x)", alg_name, pcr_sel->pcrSelections[i].hash); pcr_sel->pcrSelections[i].hash = 0; //mark it as to be removed } } shrink_pcr_selection(pcr_sel); if (pcr_sel->count == 0) return false; return true; } tool_rc pcr_read_pcr_values(ESYS_CONTEXT *esys_context, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { TPML_PCR_SELECTION pcr_selection_tmp; TPML_PCR_SELECTION *pcr_selection_out; UINT32 pcr_update_counter; //1. prepare pcrSelectionIn with g_pcrSelections memcpy(&pcr_selection_tmp, pcr_select, sizeof(pcr_selection_tmp)); //2. call pcr_read pcrs->count = 0; do { TPML_DIGEST *v; tool_rc rc = tpm2_pcr_read(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &pcr_selection_tmp, &pcr_update_counter, &pcr_selection_out, &v); if (rc != tool_rc_success) { return rc; } pcrs->pcr_values[pcrs->count] = *v; free(v); //3. unmask pcrSelectionOut bits from pcrSelectionIn pcr_update_pcr_selections(&pcr_selection_tmp, pcr_selection_out); free(pcr_selection_out); //4. goto step 2 if pcrSelctionIn still has bits set } while (++pcrs->count < ARRAY_LEN(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp)); if (pcrs->count >= ARRAY_LEN(pcrs->pcr_values) && !pcr_unset_pcr_sections(&pcr_selection_tmp)) { LOG_ERR("too much pcrs to get! try to split into multiple calls..."); return tool_rc_general_error; } return tool_rc_success; } tpm2-tools-5.2/lib/pcr.h000066400000000000000000000060001412464516500151070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_PCR_H_ #define SRC_PCR_H_ #include #include #include #include #include "tool_rc.h" typedef struct tpm2_algorithm tpm2_algorithm; struct tpm2_algorithm { int count; TPMI_ALG_HASH alg[TPM2_NUM_PCR_BANKS]; }; typedef struct tpm2_pcrs tpm2_pcrs; struct tpm2_pcrs { size_t count; TPML_DIGEST pcr_values[TPM2_MAX_PCRS]; }; /** * Echo out all PCR banks according to g_pcrSelection & g_pcrs->. * @param pcrSelect * Description of which PCR registers are selected. * @param pcrs * Struct containing PCR digests. * @return * True on success, false otherwise. */ bool pcr_print_pcr_struct(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs); /** * Echo out all PCR banks according to g_pcrSelection & g_pcrs->. * Assume that data structures are all little endian. * @param pcrSelect * Description of which PCR registers are selected. * @param pcrs * Struct containing PCR digests. * @return * True on success, false otherwise. */ bool pcr_print_pcr_struct_le(TPML_PCR_SELECTION *pcrSelect, tpm2_pcrs *pcrs); /** * Set the PCR value into pcrId if string in arg is a valid PCR index. * @param arg * PCR index as string * @param pcrId * Caller-allocated PCR index as integer * @return * True on success, false otherwise. */ bool pcr_get_id(const char *arg, UINT32 *pcr_id); bool pcr_print_pcr_selections(TPML_PCR_SELECTION *pcr_selections); /** * Prints the selected PCR values. * * @param pcr_select the selected pcrs to be printed * @param pcrs the pcrs digests * @return true on success; false otherwise */ bool pcr_print_values(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *pcrs); /** * Writes the selected PCR values to a file. * * @param pcr_select the selected pcrs to be written * @param pcrs the pcrs digests * @param output_file file to output the pcr values * @return true on success; false otherwise */ bool pcr_fwrite_values(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *pcrs, FILE *output_file); /** * Writes the selected PCR values to a file in serialized format. * * @param pcr_select the selected pcrs to be written * @param pcrs the pcrs digests * @param output_file file to output the pcr values in serialized format * @return true on success; false otherwise */ bool pcr_fwrite_serialized(const TPML_PCR_SELECTION *pcr_select, const tpm2_pcrs *pcrs, FILE *output_file); bool pcr_parse_selections(const char *arg, TPML_PCR_SELECTION *pcr_selections); tool_rc pcr_get_banks(ESYS_CONTEXT *esys_context, TPMS_CAPABILITY_DATA *capability_data, tpm2_algorithm *algs); bool pcr_init_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_selections, TPMI_ALG_HASH alg_id); bool pcr_check_pcr_selection(TPMS_CAPABILITY_DATA *cap_data, TPML_PCR_SELECTION *pcr_selections); tool_rc pcr_read_pcr_values(ESYS_CONTEXT *esys_context, TPML_PCR_SELECTION *pcr_selections, tpm2_pcrs *pcrs); #endif /* SRC_PCR_H_ */ tpm2-tools-5.2/lib/tool_rc.c000066400000000000000000000014051412464516500157630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "tool_rc.h" #define UNFMT1(x) (x - TPM2_RC_FMT1) static inline UINT16 tpm2_rc_fmt1_error_get(TPM2_RC rc) { return (rc & 0x3F); } static inline UINT8 tss2_rc_layer_format_get(TSS2_RC rc) { return ((rc & (1 << 7)) >> 7); } static tool_rc flatten_fmt1(TSS2_RC rc) { UINT8 errnum = tpm2_rc_fmt1_error_get(rc); switch (errnum) { case UNFMT1(TPM2_RC_AUTH_FAIL): return tool_rc_auth_error; default: return tool_rc_general_error; } } tool_rc tool_rc_from_tpm(TSS2_RC rc) { bool is_fmt_1 = tss2_rc_layer_format_get(rc); if (is_fmt_1) { return flatten_fmt1(rc); } return tool_rc_general_error; } tpm2-tools-5.2/lib/tool_rc.h000066400000000000000000000013301412464516500157650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TOOL_RC_H_ #define LIB_TOOL_RC_H_ /* do not port to TSS below here */ typedef enum tool_rc tool_rc; enum tool_rc { /* do not reorder or change, part of returned codes to exit */ /* maps to common/returns.md */ tool_rc_success = 0, tool_rc_general_error, tool_rc_option_error, tool_rc_auth_error, tool_rc_tcti_error, tool_rc_unsupported }; /** * Flattens a TSS generated RC into it's error component and converts it to a tool_rc suitable for tool return * use. * @note * Do not port me to TSS. * @param rc * The rc to convert. * @return * A valid tool_rc. */ tool_rc tool_rc_from_tpm(TSS2_RC rc); #endif /* LIB_TOOL_RC_H_ */ tpm2-tools-5.2/lib/tpm2.c000066400000000000000000004721701412464516500152170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "log.h" #include "object.h" #include "tool_rc.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_openssl.h" #include "tpm2_session.h" #include "tpm2_tool.h" #include "config.h" #define TPM2_ERROR_TSS2_RC_ERROR_MASK 0xFFFF static inline UINT16 tpm2_error_get(TSS2_RC rc) { return ((rc & TPM2_ERROR_TSS2_RC_ERROR_MASK)); } tool_rc tpm2_readpublic(ESYS_CONTEXT *esys_context, ESYS_TR object_handle, TPM2B_PUBLIC **out_public, TPM2B_NAME **name, TPM2B_NAME **qualified_name) { TSS2_RC rval = Esys_ReadPublic(esys_context, object_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, out_public, name, qualified_name); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ReadPublic, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_from_tpm_public(ESYS_CONTEXT *esys_context, TPM2_HANDLE tpm_handle, ESYS_TR optional_session1, ESYS_TR optional_session2, ESYS_TR optional_session3, ESYS_TR *object) { TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, tpm_handle, optional_session1, optional_session2, optional_session3, object); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_tr_deserialize(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle) { TSS2_RC rval = Esys_TR_Deserialize(esys_context, buffer, buffer_size, esys_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TR_Deserialize, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_tr_serialize(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size) { TSS2_RC rval = Esys_TR_Serialize(esys_context, object, buffer, buffer_size); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TR_Serialize, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_tr_get_name(ESYS_CONTEXT *esys_context, ESYS_TR handle, TPM2B_NAME **name) { TSS2_RC rval = Esys_TR_GetName(esys_context, handle, name); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TR_GetName, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_close(ESYS_CONTEXT *esys_context, ESYS_TR *rsrc_handle) { TSS2_RC rval = Esys_TR_Close(esys_context, rsrc_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TR_Close, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_nv_readpublic(ESYS_CONTEXT *esys_context, ESYS_TR nv_index, TPM2B_NV_PUBLIC **nv_public, TPM2B_NAME **nv_name) { TSS2_RC rval = Esys_NV_ReadPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, nv_public, nv_name); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_NV_ReadPublic, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_getcap(ESYS_CONTEXT *esys_context, TPM2_CAP capability, UINT32 property, UINT32 property_count, TPMI_YES_NO *more_data, TPMS_CAPABILITY_DATA **capability_data) { TSS2_RC rval = Esys_GetCapability(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, capability, property, property_count, more_data, capability_data); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_NV_ReadPublic, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_nv_read(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_NAME *precalc_nvname, UINT16 size, UINT16 offset, TPM2B_MAX_NV_BUFFER **data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { /* * If command is to be dispatched the NV index must exist. * In this case get the NV index name by reading its public information. * If rpHash size is non zero then command is always dispatched. */ ESYS_TR esys_tr_nv_handle = ESYS_TR_NONE; TSS2_RC rval = TSS2_RC_SUCCESS; bool is_name_specified = precalc_nvname ? precalc_nvname->size : false; if (!is_name_specified) { rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } } TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { rval = Tss2_Sys_NV_Read_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index, size, offset); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_Read_Prepare, rval); return tool_rc_general_error; } /* * We need this to use precalc-name for parent authorization when the * NV index itself is the authorization parent AND * we don't need/have the NV index defined when simply calculating cpHash. */ bool is_auth_hierarchy_nv_index = (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_OWNER) && (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_PLATFORM); /* * We need this to avoid requiring an NV-index be defined when simply * calculating cpHash. */ TPM2B_NAME *name1 = 0; if (is_auth_hierarchy_nv_index && is_name_specified) { name1 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvread_free_name1; } } TPM2B_NAME *name2 = 0; if (is_name_specified) { name2 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvread_free_name1_name2; } } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_nvread_free_name1_name2: if (!(is_name_specified)) { Esys_Free(name2); } tpm2_nvread_free_name1: if (!is_name_specified) { Esys_Free(name1); } /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_nvread_skip_esapi_call; } } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } rval = Esys_NV_Read(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, shandle2, shandle3, size, offset, data); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_NV_Read, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_nvread_skip_esapi_call: return rc; } tool_rc tpm2_context_save(ESYS_CONTEXT *esys_context, ESYS_TR save_handle, TPMS_CONTEXT **context) { TSS2_RC rval = Esys_ContextSave(esys_context, save_handle, context); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ContextSave, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_context_load(ESYS_CONTEXT *esys_context, const TPMS_CONTEXT *context, ESYS_TR *loaded_handle) { TSS2_RC rval = Esys_ContextLoad(esys_context, context, loaded_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ContextLoad, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_flush_context(ESYS_CONTEXT *esys_context, ESYS_TR flush_handle) { TSS2_RC rval = Esys_FlushContext(esys_context, flush_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_FlushContext, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_start_auth_session(ESYS_CONTEXT *esys_context, ESYS_TR tpm_key, ESYS_TR bind, const TPM2B_NONCE *nonce_caller, TPM2_SE session_type, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH auth_hash, ESYS_TR *session_handle) { TSS2_RC rval = Esys_StartAuthSession(esys_context, tpm_key, bind, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, nonce_caller, session_type, symmetric, auth_hash, session_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_StartAuthSession, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_sess_set_attributes(ESYS_CONTEXT *esys_context, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask) { TSS2_RC rval = Esys_TRSess_SetAttributes(esys_context, session, flags, mask); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TRSess_SetAttributes, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_sess_get_attributes(ESYS_CONTEXT *esys_context, ESYS_TR session, TPMA_SESSION *flags) { TSS2_RC rval = Esys_TRSess_GetAttributes(esys_context, session, flags); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TRSess_GetAttributes, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_sess_get_noncetpm(ESYS_CONTEXT *esys_context, ESYS_TR session_handle, TPM2B_NONCE **nonce_tpm) { TSS2_RC rval = Esys_TRSess_GetNonceTPM(esys_context, session_handle, nonce_tpm); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_TRSess_GetNonceTPM, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_restart(ESYS_CONTEXT *esys_context, ESYS_TR session_handle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_RC rval = Esys_PolicyRestart(esys_context, session_handle, shandle1, shandle2, shandle3); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyRestart, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_get_capability(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 property_count, TPMI_YES_NO *more_data, TPMS_CAPABILITY_DATA **capability_data) { TSS2_RC rval = Esys_GetCapability(esys_context, shandle1, shandle2, shandle3, capability, property, property_count, more_data, capability_data); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_GetCapability, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_create_primary(ESYS_CONTEXT *esys_context, ESYS_TR primary_handle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_PUBLIC *in_public, const TPM2B_DATA *outside_info, const TPML_PCR_SELECTION *creation_pcr, ESYS_TR *object_handle, TPM2B_PUBLIC **out_public, TPM2B_CREATION_DATA **creation_data, TPM2B_DIGEST **creation_hash, TPMT_TK_CREATION **creation_ticket) { TSS2_RC rval = Esys_CreatePrimary(esys_context, primary_handle, shandle1, shandle2, shandle3, in_sensitive, in_public, outside_info, creation_pcr, object_handle, out_public, creation_data, creation_hash, creation_ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_CreatePrimary, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_pcr_read(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcr_selection_in, UINT32 *pcr_update_counter, TPML_PCR_SELECTION **pcr_selection_out, TPML_DIGEST **pcr_values) { TSS2_RC rval = Esys_PCR_Read(esys_context, shandle1, shandle2, shandle3, pcr_selection_in, pcr_update_counter, pcr_selection_out, pcr_values); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PCR_Read, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_authorize(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *approved_policy, const TPM2B_NONCE *policy_ref, const TPM2B_NAME *key_sign, const TPMT_TK_VERIFIED *check_ticket) { TSS2_RC rval = Esys_PolicyAuthorize(esys_context, policy_session, shandle1, shandle2, shandle3, approved_policy, policy_ref, key_sign, check_ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyAuthorize, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_or(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST *p_hash_list) { TSS2_RC rval = Esys_PolicyOR(esys_context, policy_session, shandle1, shandle2, shandle3, p_hash_list); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyAuthorize, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_namehash(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *name_hash) { TSS2_RC rval = Esys_PolicyNameHash(esys_context, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, name_hash); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyNameHash, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_template(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *template_hash) { TSS2_RC rval = Esys_PolicyTemplate(esys_context, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, template_hash); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyTemplate, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_cphash(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *cphash) { TSS2_RC rval = Esys_PolicyCpHash(esys_context, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, cphash); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyCpHash, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_pcr(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcr_digest, const TPML_PCR_SELECTION *pcrs) { TSS2_RC rval = Esys_PolicyPCR(esys_context, policy_session, shandle1, shandle2, shandle3, pcr_digest, pcrs); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyPCR, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_password(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_RC rval = Esys_PolicyPassword(esys_context, policy_session, shandle1, shandle2, shandle3); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyPassword, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_signed(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, ESYS_TR policy_session, const TPMT_SIGNATURE *signature, INT32 expiration, TPM2B_TIMEOUT **timeout, TPMT_TK_AUTH **policy_ticket, TPM2B_NONCE *policy_qualifier, TPM2B_NONCE *nonce_tpm, TPM2B_DIGEST *cphash) { TSS2_RC rval = Esys_PolicySigned(esys_context, auth_entity_obj->tr_handle, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, nonce_tpm, cphash, policy_qualifier, expiration, signature, timeout, policy_ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicySigned, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_ticket(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_TIMEOUT *timeout, const TPM2B_NONCE *policyref, const TPM2B_NAME *authname, const TPMT_TK_AUTH *ticket) { TSS2_RC rval = Esys_PolicyTicket(esys_context, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, timeout, NULL, policyref, authname, ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicySigned, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_authvalue(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_RC rval = Esys_PolicyAuthValue(esys_context, policy_session, shandle1, shandle2, shandle3); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyAuthValue, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_authorize_nv(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, ESYS_TR policy_session, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_index; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_PolicyAuthorizeNV_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index, policy_session); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_PolicyAuthorizeNV_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_policyauthorizenv_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_index, &name2); if (rc != tool_rc_success) { goto tpm2_policyauthorizenv_free_name1_name2; } TPM2B_NAME *name3 = NULL; rc = tpm2_tr_get_name(esys_context, policy_session, &name3); if (rc != tool_rc_success) { goto tpm2_policyauthorizenv_free_name1_name2_name3; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, name3, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_policyauthorizenv_free_name1_name2_name3: Esys_Free(name3); tpm2_policyauthorizenv_free_name1_name2: Esys_Free(name2); tpm2_policyauthorizenv_free_name1: Esys_Free(name1); goto tpm2_policyauthorizenv_skip_esapi_call; } rval = Esys_PolicyAuthorizeNV(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_index, policy_session, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyAuthorizeNV, rval); return tool_rc_from_tpm(rval); } tpm2_policyauthorizenv_skip_esapi_call: return rc; } tool_rc tpm2_policy_nv(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, ESYS_TR policy_session, const TPM2B_OPERAND *operand_b, UINT16 offset, TPM2_EO operation, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_index; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_entity_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_entity_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_PolicyNV_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index, policy_session, operand_b, offset, operation); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_PolicyNV_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_policynv_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_index, &name2); if (rc != tool_rc_success) { goto tpm2_policynv_free_name1_name2; } TPM2B_NAME *name3 = NULL; rc = tpm2_tr_get_name(esys_context, policy_session, &name3); if (rc != tool_rc_success) { goto tpm2_policynv_free_name1_name2_name3; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, name3, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_policynv_free_name1_name2_name3: Esys_Free(name3); tpm2_policynv_free_name1_name2: Esys_Free(name2); tpm2_policynv_free_name1: Esys_Free(name1); goto tpm2_policynv_skip_esapi_out; } rval = Esys_PolicyNV(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_index, policy_session, auth_entity_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, operand_b, offset, operation); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyNV, rval); return tool_rc_from_tpm(rval); } tpm2_policynv_skip_esapi_out: return rc; } tool_rc tpm2_policy_countertimer(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_OPERAND *operand_b, UINT16 offset, TPM2_EO operation) { TSS2_RC rval = Esys_PolicyCounterTimer(esys_context, policy_session, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, operand_b, offset, operation); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyCounterTimer, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_secret(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, ESYS_TR policy_session, INT32 expiration, TPMT_TK_AUTH **policy_ticket, TPM2B_TIMEOUT **timeout, TPM2B_NONCE *nonce_tpm, TPM2B_NONCE *policy_qualifier, TPM2B_DIGEST *cp_hash) { const TPM2B_DIGEST *cphash = NULL; ESYS_TR auth_entity_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_entity_obj->tr_handle, auth_entity_obj->session, &auth_entity_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_PolicySecret_Prepare(sys_context, auth_entity_obj->handle, policy_session, nonce_tpm, cphash, policy_qualifier, expiration); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_PolicySecret_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_entity_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_policysecret_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, policy_session, &name2); if (rc != tool_rc_success) { goto tpm2_policysecret_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_entity_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_entity_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_policysecret_free_name1_name2: Esys_Free(name2); tpm2_policysecret_free_name1: Esys_Free(name1); goto tpm2_policysecret_skip_esapi_call; } TSS2_RC rval = Esys_PolicySecret(esys_context, auth_entity_obj->tr_handle, policy_session, auth_entity_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, nonce_tpm, cphash, policy_qualifier, expiration, timeout, policy_ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicySecret, rval); return tool_rc_from_tpm(rval); } tpm2_policysecret_skip_esapi_call: return rc; } tool_rc tpm2_policy_getdigest(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policy_digest) { TSS2_RC rval = Esys_PolicyGetDigest(esys_context, policy_session, shandle1, shandle2, shandle3, policy_digest); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyGetDigest, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_command_code(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CC code) { TSS2_RC rval = Esys_PolicyCommandCode(esys_context, policy_session, shandle1, shandle2, shandle3, code); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyCommandCode, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_setcommandcodeaudit(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, TPMI_ALG_HASH hash_algorithm, const TPML_CC *setlist, const TPML_CC *clearlist) { ESYS_TR auth_entity_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_entity_obj->tr_handle, auth_entity_obj->session, &auth_entity_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } TSS2_RC rval = Esys_SetCommandCodeAuditStatus(esys_context, auth_entity_obj->tr_handle, auth_entity_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, hash_algorithm, setlist, clearlist); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_SetCommandCodeAuditStatus, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_getcommandauditdigest(ESYS_CONTEXT *esys_context, tpm2_loaded_object *privacy_object, tpm2_loaded_object *sign_object, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPM2B_ATTEST **audit_info, TPMT_SIGNATURE **signature) { ESYS_TR privacy_object_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, privacy_object->tr_handle, privacy_object->session, &privacy_object_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } ESYS_TR sign_object_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, sign_object->tr_handle, sign_object->session, &sign_object_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } TSS2_RC rval = Esys_GetCommandAuditDigest(esys_context, privacy_object->tr_handle, sign_object->tr_handle, privacy_object_session_handle, sign_object_session_handle, ESYS_TR_NONE, qualifying_data, in_scheme, audit_info, signature); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_GetCommandAuditDigest, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } static tool_rc evaluate_sessions_for_audit(ESYS_CONTEXT *ectx, ESYS_TR audit_session_handle) { //Check if session is an audit session from the attributes TPMA_SESSION attrs; tool_rc rc = tpm2_sess_get_attributes(ectx, audit_session_handle, &attrs); if (rc != tool_rc_success) { return rc; } if (!(attrs & TPMA_SESSION_AUDIT)) { LOG_ERR("Session does not have audit attributes setup."); return tool_rc_general_error; } return tool_rc_success; } tool_rc tpm2_getsessionauditdigest(ESYS_CONTEXT *esys_context, tpm2_loaded_object *privacy_object, tpm2_loaded_object *sign_object, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPM2B_ATTEST **audit_info, TPMT_SIGNATURE **signature, ESYS_TR audit_session_handle) { tool_rc rc = audit_session_handle == ESYS_TR_NONE ? tool_rc_general_error : evaluate_sessions_for_audit(esys_context, audit_session_handle); if (rc != tool_rc_success) { return rc; } ESYS_TR privacy_object_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, privacy_object->tr_handle, privacy_object->session, &privacy_object_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } ESYS_TR sign_object_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, sign_object->tr_handle, sign_object->session, &sign_object_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get auth entity obj session"); return rc; } TSS2_RC rval = Esys_GetSessionAuditDigest(esys_context, privacy_object->tr_handle, sign_object->tr_handle, audit_session_handle, privacy_object_session_handle, sign_object_session_handle, ESYS_TR_NONE, qualifying_data, in_scheme, audit_info, signature); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_GetCommandAuditDigest, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_nv_written(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMI_YES_NO written_set) { TSS2_RC rval = Esys_PolicyNvWritten(esys_context, policy_session, shandle1, shandle2, shandle3, written_set); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyNVWritten, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_locality(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMA_LOCALITY locality) { TSS2_RC rval = Esys_PolicyLocality(esys_context, policy_session, shandle1, shandle2, shandle3, locality); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyLocality, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_policy_duplication_select(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NAME *object_name, const TPM2B_NAME *new_parent_name, TPMI_YES_NO include_object) { TSS2_RC rval = Esys_PolicyDuplicationSelect(esys_context, policy_session, shandle1, shandle2, shandle3, object_name, new_parent_name, include_object); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PolicyDuplicationSelect, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_mu_tpm2_handle_unmarshal(uint8_t const buffer[], size_t size, size_t *offset, TPM2_HANDLE *out) { TSS2_RC rval = Tss2_MU_TPM2_HANDLE_Unmarshal(buffer, size, offset, out); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Tss2_MU_TPM2_HANDLE_Unmarshal, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_mu_tpmt_public_marshal(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset) { TSS2_RC rval = Tss2_MU_TPMT_PUBLIC_Marshal(src, buffer, buffer_size, offset); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Tss2_MU_TPMT_PUBLIC_Marshal, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_evictcontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, tpm2_loaded_object *to_persist_key_obj, TPMI_DH_PERSISTENT persistent_handle, ESYS_TR *new_object_handle, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &shandle1); if (rc != tool_rc_success) { return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_EvictControl_Prepare(sys_context, auth_hierarchy_obj->handle, to_persist_key_obj->handle, persistent_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_EvictControl_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_evictcontrol_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, to_persist_key_obj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_evictcontrol_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_evictcontrol_free_name1_name2: Esys_Free(name2); tpm2_evictcontrol_free_name1: Esys_Free(name1); goto tpm2_evictcontrol_skip_esapi_call; } TSS2_RC rval = Esys_EvictControl(esys_context, auth_hierarchy_obj->tr_handle, to_persist_key_obj->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, persistent_handle, new_object_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_EvictControl, rval); return tool_rc_from_tpm(rval); } tpm2_evictcontrol_skip_esapi_call: return rc; } /* This function addresses ESAPI change that changes parameter type from * Esys_TR to TPMI_RH_HIERARCHY or TPMI_RH_ENABLES and breaks backwards * compatibility. * To keep the tools parameters consistent after v4.0 release we need to * map the values to appropriate type based on the version of the ESYS API. * Note: the mapping is based on the ESYS version recognized at compile time. * The TSS change can be found here: * https://github.com/tpm2-software/tpm2-tss/pull/1531 */ TSS2_RC fix_esys_hierarchy(uint32_t in, uint32_t *out) { #if defined(ESYS_3_0) switch (in) { case ESYS_TR_RH_NULL: /* FALLTHRU */ case ESYS_TR_RH_OWNER: /* FALLTHRU */ case ESYS_TR_RH_ENDORSEMENT: /* FALLTHRU */ case ESYS_TR_RH_PLATFORM: /* FALLTHRU */ case ESYS_TR_RH_PLATFORM_NV: *out = in; return TSS2_RC_SUCCESS; case TPM2_RH_NULL: *out = ESYS_TR_RH_NULL; return TSS2_RC_SUCCESS; case TPM2_RH_OWNER: *out = ESYS_TR_RH_OWNER; return TSS2_RC_SUCCESS; case TPM2_RH_ENDORSEMENT: *out = ESYS_TR_RH_ENDORSEMENT; return TSS2_RC_SUCCESS; case TPM2_RH_PLATFORM: *out = ESYS_TR_RH_PLATFORM; return TSS2_RC_SUCCESS; case TPM2_RH_PLATFORM_NV: *out = ESYS_TR_RH_PLATFORM_NV; return TSS2_RC_SUCCESS; default: LOG_ERR("An unknown hierarchy handle was passed: 0x%08x", in); return TSS2_ESYS_RC_BAD_VALUE; } #elif defined(ESYS_2_3) *out = in; return TSS2_RC_SUCCESS; #else #error "Need to define either ESYS_3_0 or ESYS_2_3" #endif } tool_rc tpm2_hash(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_MAX_BUFFER *data, TPMI_ALG_HASH hash_alg, TPMI_RH_HIERARCHY hierarchy, TPM2B_DIGEST **out_hash, TPMT_TK_HASHCHECK **validation) { TSS2_RC rval = fix_esys_hierarchy(hierarchy, &hierarchy); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } rval = Esys_Hash(esys_context, shandle1, shandle2, shandle3, data, hash_alg, hierarchy, out_hash, validation); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_Hash, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_hash_sequence_start(ESYS_CONTEXT *esys_context, const TPM2B_AUTH *auth, TPMI_ALG_HASH hash_alg, ESYS_TR *sequence_handle) { TSS2_RC rval = Esys_HashSequenceStart(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, auth, hash_alg, sequence_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HashSequenceStart, rval); return tool_rc_from_tpm(rval); } return tpm2_tr_set_auth(esys_context, *sequence_handle, auth); } tool_rc tpm2_sequence_update(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, const TPM2B_MAX_BUFFER *buffer) { TSS2_RC rval = Esys_SequenceUpdate(esys_context, sequence_handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, buffer); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_SequenceUpdate, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_sequence_complete(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, const TPM2B_MAX_BUFFER *buffer, TPMI_RH_HIERARCHY hierarchy, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { TSS2_RC rval = fix_esys_hierarchy(hierarchy, &hierarchy); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } rval = Esys_SequenceComplete(esys_context, sequence_handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, buffer, hierarchy, result, validation); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_SequenceComplete, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_event_sequence_complete(ESYS_CONTEXT *ectx, ESYS_TR pcr, ESYS_TR sequence_handle, tpm2_session *session, const TPM2B_MAX_BUFFER *buffer, TPML_DIGEST_VALUES **results) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, pcr, session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_EventSequenceComplete(ectx, pcr, sequence_handle, shandle1, ESYS_TR_PASSWORD, ESYS_TR_NONE, buffer, results); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_EventSequenceComplete, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_tr_set_auth(ESYS_CONTEXT *esys_context, ESYS_TR handle, TPM2B_AUTH const *auth_value) { TSS2_RC rval = Esys_TR_SetAuth(esys_context, handle, auth_value); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_SequenceComplete, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_activatecredential(ESYS_CONTEXT *esys_context, tpm2_loaded_object *activatehandleobj, tpm2_loaded_object *keyhandleobj, const TPM2B_ID_OBJECT *credential_blob, const TPM2B_ENCRYPTED_SECRET *secret, TPM2B_DIGEST **cert_info, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_ActivateCredential_Prepare(sys_context, activatehandleobj->handle, keyhandleobj->handle, credential_blob, secret); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ActivateCredential_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, activatehandleobj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_activatecredential_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, keyhandleobj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_activatecredential_free_name1_name2; } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_activatecredential_free_name1_name2: Esys_Free(name2); tpm2_activatecredential_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_activatecredential_skip_esapi_call; } } ESYS_TR keyobj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, keyhandleobj->tr_handle, keyhandleobj->session, &keyobj_session_handle); //shandle1 if (rc != tool_rc_success) { return rc; } ESYS_TR activateobj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, activatehandleobj->tr_handle, activatehandleobj->session, &activateobj_session_handle); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_ActivateCredential(esys_context, activatehandleobj->tr_handle, keyhandleobj->tr_handle, activateobj_session_handle, keyobj_session_handle, shandle3, credential_blob, secret, cert_info); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ActivateCredential, rval); rc = tool_rc_from_tpm(rval); return rc; } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_activatecredential_skip_esapi_call: return rc; } tool_rc tpm2_create(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_PUBLIC *in_public, const TPM2B_DATA *outside_info, const TPML_PCR_SELECTION *creation_pcr, TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public, TPM2B_CREATION_DATA **creation_data, TPM2B_DIGEST **creation_hash, TPMT_TK_CREATION **creation_ticket, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_Create_Prepare(sys_context, parent_obj->handle, in_sensitive, in_public, outside_info, creation_pcr); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Create_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, parent_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_create_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_create_free_name1: Esys_Free(name1); if (rc != tool_rc_success) { return rc; } /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_create_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, parent_obj->tr_handle, parent_obj->session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_Create(esys_context, parent_obj->tr_handle, shandle1, shandle2, shandle3, in_sensitive, in_public, outside_info, creation_pcr, out_private, out_public, creation_data, creation_hash, creation_ticket); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_Create, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_create_skip_esapi_call: return rc; } tool_rc tpm2_create_loaded(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_TEMPLATE *in_public, ESYS_TR *object_handle, TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_CreateLoaded_Prepare(sys_context, parent_obj->handle, in_sensitive, in_public); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_CreateLoaded_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, parent_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_createloaded_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_createloaded_free_name1: Esys_Free(name1); if (rc != tool_rc_success) { return rc; } /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_createloaded_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, parent_obj->tr_handle, parent_obj->session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_CreateLoaded(esys_context, parent_obj->tr_handle, shandle1, shandle2, shandle3, in_sensitive, in_public, object_handle, out_private, out_public); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_CreateLoaded, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_createloaded_skip_esapi_call: return rc; } tool_rc tpm2_object_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_object, tpm2_loaded_object *object, const TPM2B_AUTH *new_auth, TPM2B_PRIVATE **out_private, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_ObjectChangeAuth_Prepare(sys_context, object->handle, parent_object->handle, new_auth); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ObjectChangeAuth_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, object->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_objectchangeauth_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, parent_object->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_objectchangeauth_free_name1_name2; } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_objectchangeauth_free_name1_name2: Esys_Free(name2); tpm2_objectchangeauth_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_objectchangeauth_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, object->tr_handle, object->session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_ObjectChangeAuth(esys_context, object->tr_handle, parent_object->tr_handle, shandle1, shandle2, shandle3, new_auth, out_private); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ObjectChangeAuth, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_objectchangeauth_skip_esapi_call: return rc; } tool_rc tpm2_nv_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *nv, const TPM2B_AUTH *new_auth, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = (cp_hash->size || rp_hash->size) ? tpm2_getsapicontext(esys_context, &sys_context) : tool_rc_success; if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_NV_ChangeAuth_Prepare(sys_context, nv->handle, new_auth); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_ChangeAuth_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, nv->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvchangeauth_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_nvchangeauth_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_nvchangeauth_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, nv->tr_handle, nv->session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_NV_ChangeAuth(esys_context, nv->tr_handle, shandle1, shandle2, shandle3, new_auth); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_ChangeAuth, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_nvchangeauth_skip_esapi_call: return rc; } tool_rc tpm2_hierarchy_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hierarchy, const TPM2B_AUTH *new_auth, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = (cp_hash->size || rp_hash->size) ? tpm2_getsapicontext(esys_context, &sys_context) : tool_rc_success; if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_HierarchyChangeAuth_Prepare(sys_context, hierarchy->handle, new_auth); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_HierarchyChangeAuth_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_hierarchychangeauth_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_hierarchychangeauth_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_hierarchychangeauth_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, hierarchy->tr_handle, hierarchy->session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_HierarchyChangeAuth(esys_context, hierarchy->tr_handle, shandle1, shandle2, shandle3, new_auth); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_HierarchyChangeAuth, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_hierarchychangeauth_skip_esapi_call: return rc; } tool_rc tpm2_certify(ESYS_CONTEXT *ectx, tpm2_loaded_object *certifiedkey_obj, tpm2_loaded_object *signingkey_obj, TPM2B_DATA *qualifying_data, TPMT_SIG_SCHEME *scheme, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_Certify_Prepare(sys_context, certifiedkey_obj->handle, signingkey_obj->handle, qualifying_data, scheme); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Certify_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, certifiedkey_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_certify_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(ectx, signingkey_obj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_certify_free_name1_name2; } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_certify_free_name1_name2: Esys_Free(name2); tpm2_certify_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_certify_skip_esapi_call; } } ESYS_TR certifiedkey_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(ectx, certifiedkey_obj->tr_handle, certifiedkey_obj->session, &certifiedkey_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get session handle for TPM object"); return rc; } ESYS_TR signingkey_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(ectx, signingkey_obj->tr_handle, signingkey_obj->session, &signingkey_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get session handle for key"); return rc; } TSS2_RC rval = Esys_Certify(ectx, certifiedkey_obj->tr_handle, signingkey_obj->tr_handle, certifiedkey_session_handle, signingkey_session_handle, shandle3, qualifying_data, scheme, certify_info, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Eys_Certify, rval); rc = tool_rc_from_tpm(rval); return rc; } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_certify_skip_esapi_call: return rc; } tool_rc tpm2_rsa_decrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj, const TPM2B_PUBLIC_KEY_RSA *cipher_text, const TPMT_RSA_DECRYPT *scheme, const TPM2B_DATA *label, TPM2B_PUBLIC_KEY_RSA **message, TPM2B_DIGEST *cp_hash) { ESYS_TR keyobj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, keyobj->tr_handle, keyobj->session, &keyobj_session_handle); if (rc != tool_rc_success) { return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_RSA_Decrypt_Prepare(sys_context, keyobj->handle, cipher_text, scheme, label); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_RSA_Decrypt_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, keyobj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_rsadecrypt_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(keyobj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(keyobj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_rsadecrypt_free_name1: Esys_Free(name1); goto tpm2_rsadecrypt_skip_esapi_call; } TSS2_RC rval = Esys_RSA_Decrypt(ectx, keyobj->tr_handle, keyobj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, cipher_text, scheme, label, message); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_RSA_Decrypt, rval); return tool_rc_from_tpm(rval); } tpm2_rsadecrypt_skip_esapi_call: return rc; } tool_rc tpm2_rsa_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj, const TPM2B_PUBLIC_KEY_RSA *message, const TPMT_RSA_DECRYPT *scheme, const TPM2B_DATA *label, TPM2B_PUBLIC_KEY_RSA **cipher_text) { TSS2_RC rval = Esys_RSA_Encrypt(ectx, keyobj->tr_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, message, scheme, label, cipher_text); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_RSA_Encrypt, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_load(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parentobj, const TPM2B_PRIVATE *in_private, const TPM2B_PUBLIC *in_public, ESYS_TR *object_handle, TPM2B_DIGEST *cp_hash) { ESYS_TR parent_object_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, parentobj->tr_handle, parentobj->session, &parent_object_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get parent object session handle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Load_Prepare(sys_context, parentobj->handle, in_private, in_public); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Load_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, parentobj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_load_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(parentobj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(parentobj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_load_free_name1: Esys_Free(name1); goto tpm2_load_skip_esapi_call; } TSS2_RC rval = Esys_Load(esys_context, parentobj->tr_handle, parent_object_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, in_private, in_public, object_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Eys_Load, rval); return tool_rc_from_tpm(rval); } tpm2_load_skip_esapi_call: return rc; } tool_rc tpm2_clear(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy->tr_handle, auth_hierarchy->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle for hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Clear_Prepare(sys_context, auth_hierarchy->handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Clear_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_clear_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_clear_free_name1: Esys_Free(name1); goto tpm2_clear_skip_esapi_call; } TSS2_RC rval = Esys_Clear(esys_context, auth_hierarchy->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS && rval != TPM2_RC_INITIALIZE) { LOG_PERR(Esys_Clear, rval); return tool_rc_from_tpm(rval); } tpm2_clear_skip_esapi_call: return rc; } tool_rc tpm2_clearcontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPMI_YES_NO disable_clear, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy->tr_handle, auth_hierarchy->session, &shandle); if (rc != tool_rc_success) { return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_ClearControl_Prepare(sys_context, auth_hierarchy->handle, disable_clear); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ClearControl_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_clearcontrol_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_clearcontrol_free_name1: Esys_Free(name1); goto tpm2_clearcontrol_skip_esapi_call; } TSS2_RC rval = Esys_ClearControl(esys_context, auth_hierarchy->tr_handle, shandle, ESYS_TR_NONE, ESYS_TR_NONE, disable_clear); if (rval != TPM2_RC_SUCCESS && rval != TPM2_RC_INITIALIZE) { LOG_PERR(Esys_ClearControl, rval); return tool_rc_from_tpm(rval); } tpm2_clearcontrol_skip_esapi_call: return rc; } tool_rc tpm2_dictionarylockout_setup(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, UINT32 max_tries, UINT32 recovery_time, UINT32 lockout_recovery_time, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy->tr_handle, auth_hierarchy->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for lockout hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_DictionaryAttackParameters_Prepare(sys_context, auth_hierarchy->handle, max_tries, recovery_time, lockout_recovery_time); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_DictionaryAttackParameters_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_dictionary_parameters_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_dictionary_parameters_free_name1: Esys_Free(name1); goto tpm2_dictionary_parameters_skip_esapi_call; } LOG_INFO("Setting up Dictionary Lockout parameters."); TPM2_RC rval = Esys_DictionaryAttackParameters(esys_context, auth_hierarchy->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, max_tries, recovery_time, lockout_recovery_time); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_DictionaryAttackParameters, rval); return tool_rc_from_tpm(rval); } tpm2_dictionary_parameters_skip_esapi_call: return rc; } tool_rc tpm2_dictionarylockout_reset(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy->tr_handle, auth_hierarchy->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for lockout hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_DictionaryAttackLockReset_Prepare(sys_context, auth_hierarchy->handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_DictionaryAttackLockReset_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_dictionary_attack_reset_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_dictionary_attack_reset_free_name1: Esys_Free(name1); goto tpm2_dictionary_attack_reset_skip_esapi_call; } LOG_INFO("Resetting dictionary lockout state."); TPM2_RC rval = Esys_DictionaryAttackLockReset(esys_context, auth_hierarchy->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_DictionaryAttackLockReset, rval); return tool_rc_from_tpm(rval); } tpm2_dictionary_attack_reset_skip_esapi_call: return rc; } tool_rc tpm2_duplicate(ESYS_CONTEXT *esys_context, tpm2_loaded_object *duplicable_key, tpm2_loaded_object *new_parent, const TPM2B_DATA *in_key, const TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_DATA **out_key, TPM2B_PRIVATE **duplicate, TPM2B_ENCRYPTED_SECRET **encrypted_seed, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, duplicable_key->tr_handle, duplicable_key->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Duplicate_Prepare(sys_context, duplicable_key->handle, new_parent->handle, in_key, sym_alg); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Duplicate_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, duplicable_key->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_duplicate_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, new_parent->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_duplicate_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(duplicable_key->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(duplicable_key->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_duplicate_free_name1_name2: Esys_Free(name2); tpm2_duplicate_free_name1: Esys_Free(name1); goto tpm2_duplicate_skip_esapi_call; } TSS2_RC rval = Esys_Duplicate(esys_context, duplicable_key->tr_handle, new_parent->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, in_key, sym_alg, out_key, duplicate, encrypted_seed); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Duplicate, rval); return tool_rc_from_tpm(rval); } tpm2_duplicate_skip_esapi_call: return rc; } tool_rc tpm2_encryptdecrypt(ESYS_CONTEXT *esys_context, tpm2_loaded_object *encryption_key_obj, TPMI_YES_NO decrypt, TPMI_ALG_SYM_MODE mode, const TPM2B_IV *iv_in, const TPM2B_MAX_BUFFER *input_data, TPM2B_MAX_BUFFER **output_data, TPM2B_IV **iv_out, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, encryption_key_obj->tr_handle, encryption_key_obj->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } /* Keep track of which version you ran for error reporting.*/ unsigned version = 2; if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_EncryptDecrypt2_Prepare(sys_context, encryption_key_obj->handle, input_data, decrypt, mode, iv_in); if (tpm2_error_get(rval) == TPM2_RC_COMMAND_CODE) { version = 1; rval = Tss2_Sys_EncryptDecrypt_Prepare(sys_context, encryption_key_obj->handle, decrypt, mode, iv_in, input_data); } if (rval != TPM2_RC_SUCCESS) { if (version == 2) { LOG_PERR(Tss2_Sys_EncryptDecrypt2_Prepare, rval); } else { LOG_PERR(Tss2_Sys_EncryptDecrypt_Prepare, rval); } return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, encryption_key_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_encryptdecrypt_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(encryption_key_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(encryption_key_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_encryptdecrypt_free_name1: Esys_Free(name1); goto tpm2_encryptdecrypt_skip_esapi_call; } TSS2_RC rval = Esys_EncryptDecrypt2(esys_context, encryption_key_obj->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, input_data, decrypt, mode, iv_in, output_data, iv_out); if (tpm2_error_get(rval) == TPM2_RC_COMMAND_CODE) { version = 1; rval = Esys_EncryptDecrypt(esys_context, encryption_key_obj->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, decrypt, mode, iv_in, input_data, output_data, iv_out); } if (rval != TPM2_RC_SUCCESS) { if (version == 2) { LOG_PERR(Esys_EncryptDecrypt2, rval); } else { LOG_PERR(Esys_EncryptDecrypt, rval); } return tool_rc_from_tpm(rval); } tpm2_encryptdecrypt_skip_esapi_call: return rc; } tool_rc tpm2_hierarchycontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPMI_RH_ENABLES enable, TPMI_YES_NO state, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy->tr_handle, auth_hierarchy->session, &shandle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle for hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_HierarchyControl_Prepare(sys_context, auth_hierarchy->handle, enable, state); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_HierarchyControl_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_hierarchycontrol_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_hierarchycontrol_free_name1: Esys_Free(name1); goto tpm2_hierarchycontrol_skip_esapi_call; } TSS2_RC rval = fix_esys_hierarchy(enable, &enable); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } rval = Esys_HierarchyControl(esys_context, auth_hierarchy->tr_handle, shandle, ESYS_TR_NONE, ESYS_TR_NONE, enable, state); if (rval != TPM2_RC_SUCCESS && rval != TPM2_RC_INITIALIZE) { LOG_PERR(Esys_HierarchyControl, rval); return tool_rc_from_tpm(rval); } tpm2_hierarchycontrol_skip_esapi_call: return rc; } tool_rc tpm2_hmac(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hmac_key_obj, TPMI_ALG_HASH halg, const TPM2B_MAX_BUFFER *input_buffer, TPM2B_DIGEST **out_hmac, TPM2B_DIGEST *cp_hash) { ESYS_TR hmac_key_obj_shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, hmac_key_obj->tr_handle, hmac_key_obj->session, &hmac_key_obj_shandle); if (rc != tool_rc_success) { LOG_ERR("Failed to get hmac_key_obj_shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_HMAC_Prepare(sys_context, hmac_key_obj->handle, input_buffer, halg); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_HMAC_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, hmac_key_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_hmac_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(hmac_key_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(hmac_key_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_hmac_free_name1: Esys_Free(name1); goto tpm2_hmac_skip_esapi_call; } TPM2_RC rval = Esys_HMAC(esys_context, hmac_key_obj->tr_handle, hmac_key_obj_shandle, ESYS_TR_NONE, ESYS_TR_NONE, input_buffer, halg, out_hmac); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HMAC, rval); return tool_rc_from_tpm(rval); } tpm2_hmac_skip_esapi_call: return rc; } tool_rc tpm2_hmac_start(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hmac_key_obj, TPMI_ALG_HASH halg, ESYS_TR *sequence_handle) { ESYS_TR hmac_key_obj_shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, hmac_key_obj->tr_handle, hmac_key_obj->session, &hmac_key_obj_shandle); if (rc != tool_rc_success) { LOG_ERR("Failed to get hmac_key_obj_shandle"); return rc; } TPM2B_AUTH null_auth = { .size = 0 }; TPM2_RC rval = Esys_HMAC_Start(esys_context, hmac_key_obj->tr_handle, hmac_key_obj_shandle, ESYS_TR_NONE, ESYS_TR_NONE, &null_auth, halg, sequence_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HMAC, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_hmac_sequenceupdate(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, tpm2_loaded_object *hmac_key_obj, const TPM2B_MAX_BUFFER *input_buffer) { ESYS_TR hmac_key_obj_shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, hmac_key_obj->tr_handle, hmac_key_obj->session, &hmac_key_obj_shandle); if (rc != tool_rc_success) { LOG_ERR("Failed to get hmac_key_obj_shandle"); return rc; } TPM2_RC rval = Esys_SequenceUpdate(esys_context, sequence_handle, hmac_key_obj_shandle, ESYS_TR_NONE, ESYS_TR_NONE, input_buffer); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HMAC, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_hmac_sequencecomplete(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, tpm2_loaded_object *hmac_key_obj, const TPM2B_MAX_BUFFER *input_buffer, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { ESYS_TR hmac_key_obj_shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, hmac_key_obj->tr_handle, hmac_key_obj->session, &hmac_key_obj_shandle); if (rc != tool_rc_success) { LOG_ERR("Failed to get hmac_key_obj_shandle"); return rc; } uint32_t hierarchy; TSS2_RC rval = fix_esys_hierarchy(TPM2_RH_NULL, &hierarchy); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } rval = Esys_SequenceComplete(esys_context, sequence_handle, hmac_key_obj_shandle, ESYS_TR_NONE, ESYS_TR_NONE, input_buffer, hierarchy, result, validation); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HMAC, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_import(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_DATA *encryption_key, const TPM2B_PUBLIC *object_public, const TPM2B_PRIVATE *duplicate, const TPM2B_ENCRYPTED_SECRET *in_sym_seed, const TPMT_SYM_DEF_OBJECT *symmetric_alg, TPM2B_PRIVATE **out_private, TPM2B_DIGEST *cp_hash) { ESYS_TR parentobj_shandle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, parent_obj->tr_handle, parent_obj->session, &parentobj_shandle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for phandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Import_Prepare(sys_context, parent_obj->handle, encryption_key, object_public, duplicate, in_sym_seed, symmetric_alg); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Import_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, parent_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_import_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(parent_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(parent_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_import_free_name1: Esys_Free(name1); goto tpm2_import_skip_esapi_call; } TPM2_RC rval = Esys_Import(esys_context, parent_obj->tr_handle, parentobj_shandle, ESYS_TR_NONE, ESYS_TR_NONE, encryption_key, object_public, duplicate, in_sym_seed, symmetric_alg, out_private); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_HMAC, rval); return tool_rc_from_tpm(rval); } tpm2_import_skip_esapi_call: return rc; } tool_rc tpm2_nv_definespace(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, const TPM2B_AUTH *auth, const TPM2B_NV_PUBLIC *public_info, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_NV_DefineSpace_Prepare(sys_context, auth_hierarchy_obj->handle, auth, public_info); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_DefineSpace_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvdefinespace_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_nvdefinespace_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_nvdefinespace_skip_esapi_call; } } ESYS_TR shandle1 = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } ESYS_TR nvHandle; TSS2_RC rval = Esys_NV_DefineSpace(esys_context, auth_hierarchy_obj->tr_handle, shandle1, shandle2, shandle3, auth, public_info, &nvHandle); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Failed to define NV area at index 0x%X", public_info->nvPublic.nvIndex); LOG_PERR(Esys_NV_DefineSpace, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_nvdefinespace_skip_esapi_call: return rc; } tool_rc tpm2_nv_increment(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash) { ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } // Convert TPM2_HANDLE ctx.nv_index to an ESYS_TR ESYS_TR esys_tr_nv_index; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_Increment_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_Increment_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvincrement_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_index, &name2); if (rc != tool_rc_success) { goto tpm2_nvincrement_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvincrement_free_name1_name2: Esys_Free(name2); tpm2_nvincrement_free_name1: Esys_Free(name1); goto tpm2_nvincrement_skip_esapi_call; } rval = Esys_NV_Increment(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_index, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { return tool_rc_from_tpm(rval); } tpm2_nvincrement_skip_esapi_call: return rc; } tool_rc tpm2_nvreadlock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_handle; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_ReadLock_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_ReadLock_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_readlock_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvreadlock_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvreadlock_free_name1_name2: Esys_Free(name2); tpm2_readlock_free_name1: Esys_Free(name1); goto tpm2_nvreadlock_skip_esapi_call; } rval = Esys_NV_ReadLock(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_ReadLock, rval); return tool_rc_from_tpm(rval); } tpm2_nvreadlock_skip_esapi_call: return rc; } tool_rc tpm2_nvwritelock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_handle; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_WriteLock_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_WriteLock_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvwritelock_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvwritelock_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvwritelock_free_name1_name2: Esys_Free(name2); tpm2_nvwritelock_free_name1: Esys_Free(name1); goto tpm2_nvwritelock_skip_esapi_call; } rval = Esys_NV_WriteLock(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_WriteLock, rval); return tool_rc_from_tpm(rval); } tpm2_nvwritelock_skip_esapi_call: return rc; } tool_rc tpm2_nvglobalwritelock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2B_DIGEST *cp_hash) { ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_NV_GlobalWriteLock_Prepare(sys_context, auth_hierarchy_obj->handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_GlobalWriteLock_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_globalnvwritelock_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_globalnvwritelock_free_name1: Esys_Free(name1); goto tpm2_globalnvwritelock_skip_esapi_call; } TSS2_RC rval = Esys_NV_GlobalWriteLock(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_GlobalWriteLock, rval); return tool_rc_from_tpm(rval); } tpm2_globalnvwritelock_skip_esapi_call: return rc; } tool_rc tpm2_tr_from_tpm_public(ESYS_CONTEXT *esys_context, TPM2_HANDLE handle, ESYS_TR *tr_handle) { TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, tr_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_nvsetbits(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, UINT64 bits, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, TPM2B_NAME *precalc_nvname, ESYS_TR shandle2, ESYS_TR shandle3) { /* * If command is to be dispatched the NV index must exist. * In this case get the NV index name by reading its public information. * If rpHash size is non zero then command is always dispatched. */ ESYS_TR esys_tr_nv_handle = ESYS_TR_NONE; TSS2_RC rval = TSS2_RC_SUCCESS; bool is_name_specified = precalc_nvname ? precalc_nvname->size : false; if (!is_name_specified) { rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } } TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { rval = Tss2_Sys_NV_SetBits_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index, bits); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_SetBits_Prepare, rval); return tool_rc_general_error; } /* * We need this to use precalc-name for parent authorization when the * NV index itself is the authorization parent AND * we don't need/have the NV index defined when simply calculating cpHash. */ bool is_auth_hierarchy_nv_index = (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_OWNER) && (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_PLATFORM); TPM2B_NAME *name1 = 0; if (is_auth_hierarchy_nv_index && is_name_specified) { name1 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvsetbits_free_name1; } } TPM2B_NAME *name2 = 0; if (is_name_specified) { name2 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvsetbits_free_name1_name2; } } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_nvsetbits_free_name1_name2: if (!is_name_specified) { Esys_Free(name2); } tpm2_nvsetbits_free_name1: if (!is_name_specified) { Esys_Free(name1); } /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_nvsetbits_skip_esapi_call; } } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } rval = Esys_NV_SetBits(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, shandle2, shandle3, bits); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_SetBits, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_nvsetbits_skip_esapi_call: return rc; } tool_rc tpm2_nvextend(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_MAX_NV_BUFFER *data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, TPM2B_NAME *precalc_nvname, ESYS_TR shandle2, ESYS_TR shandle3) { /* * If command is to be dispatched the NV index must exist. * In this case get the NV index name by reading its public information. * If rpHash size is non zero then command is always dispatched. */ ESYS_TR esys_tr_nv_handle = ESYS_TR_NONE; TSS2_RC rval = TSS2_RC_SUCCESS; bool is_name_specified = precalc_nvname ? precalc_nvname->size : false; if (!is_name_specified) { rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } } TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { rval = Tss2_Sys_NV_Extend_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index, data); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_Extend_Prepare, rval); return tool_rc_general_error; } /* * We need this to use precalc-name for parent authorization when the * NV index itself is the authorization parent AND * we don't need/have the NV index defined when simply calculating cpHash. */ bool is_auth_hierarchy_nv_index = (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_OWNER) && (auth_hierarchy_obj->tr_handle != ESYS_TR_RH_PLATFORM); TPM2B_NAME *name1 = 0; if (is_auth_hierarchy_nv_index && is_name_specified) { name1 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvextend_free_name1; } } TPM2B_NAME *name2 = 0; if (is_name_specified) { name2 = precalc_nvname; } else { rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvextend_free_name1_name2; } } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_nvextend_free_name1_name2: if (!is_name_specified) { Esys_Free(name2); } tpm2_nvextend_free_name1: if (!is_name_specified) { Esys_Free(name1); } /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_nvextend_skip_esapi_call; } } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } rval = Esys_NV_Extend(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, shandle2, shandle3, data); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_Extend, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_nvextend_skip_esapi_call: return rc; } tool_rc tpm2_nvundefine(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_handle; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_UndefineSpace_Prepare(sys_context, auth_hierarchy_obj->handle, nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_UndefineSpace_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvundefine_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvundefine_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvundefine_free_name1_name2: Esys_Free(name2); tpm2_nvundefine_free_name1: Esys_Free(name1); goto tpm2_nvundefine_skip_esapi_call; } rval = Esys_NV_UndefineSpace(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_handle, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Failed to release NV area at index 0x%X", nv_index); LOG_PERR(Esys_NV_UndefineSpace, rval); return tool_rc_from_tpm(rval); } LOG_INFO("Success to release NV area at index 0x%x.", nv_index); tpm2_nvundefine_skip_esapi_call: return rc; } tool_rc tpm2_nvundefinespecial(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, tpm2_session *policy_session, TPM2B_DIGEST *cp_hash) { ESYS_TR esys_tr_nv_handle; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle"); return rc; } ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session); if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_UndefineSpaceSpecial_Prepare(sys_context, nv_index, auth_hierarchy_obj->handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_UndefineSpaceSpecial_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvundefinespecial_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvundefinespecial_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvundefinespecial_free_name1_name2: Esys_Free(name2); tpm2_nvundefinespecial_free_name1: Esys_Free(name1); goto tpm2_nvundefinespecial_skip_esapi_call; } rval = Esys_NV_UndefineSpaceSpecial(esys_context, esys_tr_nv_handle, auth_hierarchy_obj->tr_handle, policy_session_handle, // policy session auth_hierarchy_obj_session_handle, // auth session for hierarchy ESYS_TR_NONE); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Failed to release NV area at index 0x%X", nv_index); LOG_PERR(Esys_NV_UndefineSpaceSpecial, rval); return tool_rc_from_tpm(rval); } LOG_INFO("Success to release NV area at index 0x%x.", nv_index); tpm2_nvundefinespecial_skip_esapi_call: return rc; } tool_rc tpm2_nvwrite(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nvindex, const TPM2B_MAX_NV_BUFFER *data, UINT16 offset, TPM2B_DIGEST *cp_hash) { // Convert TPM2_HANDLE ctx.nv_index to an ESYS_TR ESYS_TR esys_tr_nv_index; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nvindex, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, auth_hierarchy_obj->tr_handle, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_Write_Prepare(sys_context, auth_hierarchy_obj->handle, nvindex, data, offset); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_Write_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, auth_hierarchy_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvwrite_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_index, &name2); if (rc != tool_rc_success) { goto tpm2_nvwrite_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(auth_hierarchy_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(auth_hierarchy_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvwrite_free_name1_name2: Esys_Free(name2); tpm2_nvwrite_free_name1: Esys_Free(name1); goto tpm2_nvwrite_skip_esapi_call; } rval = Esys_NV_Write(esys_context, auth_hierarchy_obj->tr_handle, esys_tr_nv_index, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, data, offset); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Failed to write NV area at index 0x%X", nvindex); LOG_PERR(Tss2_Sys_NV_Write, rval); return tool_rc_from_tpm(rval); } LOG_INFO("Success to write NV area at index 0x%x offset 0x%x.", nvindex, offset); tpm2_nvwrite_skip_esapi_call: return rc; } tool_rc tpm2_pcr_allocate(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, const TPML_PCR_SELECTION *pcr_allocation) { TSS2_RC rval; TPMI_YES_NO allocation_success; UINT32 max_pcr; UINT32 size_needed; UINT32 size_available; ESYS_TR auth_hierarchy_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, ESYS_TR_RH_PLATFORM, auth_hierarchy_obj->session, &auth_hierarchy_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for lockout hierarchy"); return rc; } rval = Esys_PCR_Allocate(esys_context, ESYS_TR_RH_PLATFORM, auth_hierarchy_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, pcr_allocation, &allocation_success, &max_pcr, &size_needed, &size_available); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Could not allocate PCRs."); LOG_PERR(Esys_PCR_Allocate, rval); return tool_rc_from_tpm(rval); } if (!allocation_success) { LOG_ERR("Allocation failed. " "MaxPCR: %i, Size Needed: %i, Size available: %i", max_pcr, size_needed, size_available); return tool_rc_general_error; } return tool_rc_success; } tool_rc tpm2_sign(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, TPM2B_DIGEST *digest, TPMT_SIG_SCHEME *in_scheme, TPMT_TK_HASHCHECK *validation, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash) { ESYS_TR signingkey_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, signingkey_obj->tr_handle, signingkey_obj->session, &signingkey_obj_session_handle); if (rc != tool_rc_success) { return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Sign_Prepare(sys_context, signingkey_obj->handle, digest, in_scheme, validation); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Sign_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, signingkey_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_sign_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(signingkey_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(signingkey_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_sign_free_name1: Esys_Free(name1); goto tpm2_sign_skip_esapi_call; } TSS2_RC rval = Esys_Sign(esys_context, signingkey_obj->tr_handle, signingkey_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, digest, in_scheme, validation, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Eys_Sign, rval); rc = tool_rc_from_tpm(rval); return rc; } tpm2_sign_skip_esapi_call: return rc; } tool_rc tpm2_nvcertify(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, tpm2_loaded_object *nvindex_authobj, TPM2_HANDLE nv_index, UINT16 offset, UINT16 size, TPMT_SIG_SCHEME *in_scheme, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DATA *policy_qualifier, TPM2B_DIGEST *cp_hash) { ESYS_TR signingkey_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, signingkey_obj->tr_handle, signingkey_obj->session, &signingkey_obj_session_handle); if (rc != tool_rc_success) { return rc; } ESYS_TR nvindex_authobj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, nvindex_authobj->tr_handle, nvindex_authobj->session, &nvindex_authobj_session_handle); if (rc != tool_rc_success) { return rc; } ESYS_TR esys_tr_nv_index; TSS2_RC rval = Esys_TR_FromTPMPublic(esys_context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &esys_tr_nv_index); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_FromTPMPublic, rval); return tool_rc_from_tpm(rval); } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } rval = Tss2_Sys_NV_Certify_Prepare(sys_context, signingkey_obj->handle, nvindex_authobj->handle, nv_index, policy_qualifier, in_scheme, size, offset); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_NV_Certify_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, signingkey_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_nvcertify_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, nvindex_authobj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_nvcertify_free_name1_name2; } TPM2B_NAME *name3 = NULL; rc = tpm2_tr_get_name(esys_context, esys_tr_nv_index, &name3); if (rc != tool_rc_success) { goto tpm2_nvcertify_free_name1_name2_name3; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(signingkey_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, name3, tpm2_session_get_authhash(signingkey_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_nvcertify_free_name1_name2_name3: Esys_Free(name3); tpm2_nvcertify_free_name1_name2: Esys_Free(name2); tpm2_nvcertify_free_name1: Esys_Free(name1); goto tpm2_nvcertify_skip_esapi_call; } rval = Esys_NV_Certify(esys_context, signingkey_obj->tr_handle, nvindex_authobj->tr_handle, esys_tr_nv_index, signingkey_obj_session_handle, nvindex_authobj_session_handle, ESYS_TR_NONE, policy_qualifier, in_scheme, size, offset, certify_info, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_NV_Certify, rval); return tool_rc_from_tpm(rval); } tpm2_nvcertify_skip_esapi_call: return rc; } tool_rc tpm2_certifycreation(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, tpm2_loaded_object *certifiedkey_obj, TPM2B_DIGEST *creation_hash, TPMT_SIG_SCHEME *in_scheme, TPMT_TK_CREATION *creation_ticket, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DATA *policy_qualifier, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_CertifyCreation_Prepare(sys_context, signingkey_obj->handle, certifiedkey_obj->handle, policy_qualifier, creation_hash, in_scheme, creation_ticket); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_CertifyCreation_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, signingkey_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_certifycreation_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(esys_context, certifiedkey_obj->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_certifycreation_free_name1_name2; } rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, parameter_hash_algorithm, cp_hash); tpm2_certifycreation_free_name1_name2: Esys_Free(name2); tpm2_certifycreation_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_certifycreation_skip_esapi_call; } } ESYS_TR signingkey_obj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, signingkey_obj->tr_handle, signingkey_obj->session, &signingkey_obj_session_handle); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_CertifyCreation(esys_context, signingkey_obj->tr_handle, certifiedkey_obj->tr_handle, signingkey_obj_session_handle, shandle2, shandle3, policy_qualifier, creation_hash, in_scheme, creation_ticket, certify_info, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_CertifyCreation, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_certifycreation_skip_esapi_call: return rc; } tool_rc tpm2_setprimarypolicy(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hierarchy_object, TPM2B_DIGEST *auth_policy, TPMI_ALG_HASH hash_algorithm, TPM2B_DIGEST *cp_hash) { ESYS_TR hierarchy_object_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, hierarchy_object->tr_handle, hierarchy_object->session, &hierarchy_object_session_handle); if (rc != tool_rc_success) { return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_SetPrimaryPolicy_Prepare(sys_context, hierarchy_object->handle, auth_policy, hash_algorithm); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_SetPrimaryPolicy_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, hierarchy_object->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_setprimarypolicy_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(hierarchy_object->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(hierarchy_object->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_setprimarypolicy_free_name1: Esys_Free(name1); goto tpm2_setprimarypolicy_skip_esapi_call; } TSS2_RC rval = Esys_SetPrimaryPolicy(esys_context, hierarchy_object->tr_handle, hierarchy_object_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, auth_policy, hash_algorithm); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_SetPrimaryPolicy, rval); return tool_rc_from_tpm(rval); } tpm2_setprimarypolicy_skip_esapi_call: return rc; } tool_rc tpm2_quote(ESYS_CONTEXT *esys_context, tpm2_loaded_object *quote_obj, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPML_PCR_SELECTION *pcr_select, TPM2B_ATTEST **quoted, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash) { ESYS_TR quote_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, quote_obj->tr_handle, quote_obj->session, "e_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_Quote_Prepare(sys_context, quote_obj->handle, qualifying_data, in_scheme, pcr_select); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Quote_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, quote_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_quote_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(quote_obj->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(quote_obj->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_quote_free_name1: Esys_Free(name1); goto tpm2_quote_skip_esapi_call; } TSS2_RC rval = Esys_Quote(esys_context, quote_obj->tr_handle, quote_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, qualifying_data, in_scheme, pcr_select, quoted, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Quote, rval); return tool_rc_from_tpm(rval); } tpm2_quote_skip_esapi_call: return rc; } tool_rc tpm2_changeeps(ESYS_CONTEXT *ectx, tpm2_session *platform_hierarchy_session, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_ChangeEPS_Prepare(sys_context, TPM2_RH_PLATFORM); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ObjectChangeAuth_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, ESYS_TR_RH_PLATFORM ,&name1); if (rc != tool_rc_success) { goto tpm2_changeeps_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_changeeps_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_changeeps_skip_esapi_call; } } ESYS_TR platform_hierarchy_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(ectx, ESYS_TR_RH_PLATFORM, platform_hierarchy_session, &platform_hierarchy_session_handle); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_ChangeEPS(ectx, ESYS_TR_RH_PLATFORM, platform_hierarchy_session_handle, shandle2, shandle3); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ChangeEPS, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_changeeps_skip_esapi_call: return rc; } tool_rc tpm2_changepps(ESYS_CONTEXT *ectx, tpm2_session *platform_hierarchy_session, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = (cp_hash->size || rp_hash->size) ? tpm2_getsapicontext(ectx, &sys_context) : tool_rc_success; if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_ChangePPS_Prepare(sys_context, TPM2_RH_PLATFORM); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ObjectChangeAuth_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, ESYS_TR_RH_PLATFORM ,&name1); if (rc != tool_rc_success) { goto tpm2_changepps_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_changepps_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_changepps_skip_esapi_call; } } ESYS_TR platform_hierarchy_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(ectx, ESYS_TR_RH_PLATFORM, platform_hierarchy_session, &platform_hierarchy_session_handle); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_ChangePPS(ectx, ESYS_TR_RH_PLATFORM, platform_hierarchy_session_handle, shandle2, shandle3); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ChangePPS, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_changepps_skip_esapi_call: return rc; } tool_rc tpm2_unseal(ESYS_CONTEXT *esys_context, tpm2_loaded_object *sealkey_obj, TPM2B_SENSITIVE_DATA **out_data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(esys_context, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_Unseal_Prepare(sys_context, sealkey_obj->handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_Unseal_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(esys_context, sealkey_obj->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_unseal_free_name1; } rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, parameter_hash_algorithm, cp_hash); tpm2_unseal_free_name1: Esys_Free(name1); /* * Exit here without making the ESYS call since we just need the cpHash */ if (!rp_hash->size) { goto tpm2_unseal_skip_esapi_call; } } ESYS_TR sealkey_obj_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(esys_context, sealkey_obj->tr_handle, sealkey_obj->session, &sealkey_obj_session_handle); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_Unseal(esys_context, sealkey_obj->tr_handle, sealkey_obj_session_handle, shandle2, shandle3, out_data); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Unseal, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_unseal_skip_esapi_call: return rc; } tool_rc tpm2_incrementalselftest(ESYS_CONTEXT *ectx, const TPML_ALG *to_test, TPML_ALG **to_do_list) { TSS2_RC rval = Esys_IncrementalSelfTest(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, to_test, to_do_list); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_IncrementalSelfTest, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_stirrandom(ESYS_CONTEXT *ectx, const TPM2B_SENSITIVE_DATA *data) { TSS2_RC rval = Esys_StirRandom(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, data); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_StirRandom, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_selftest(ESYS_CONTEXT *ectx, TPMI_YES_NO full_test) { TSS2_RC rval = Esys_SelfTest(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, full_test); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_SelfTest, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_gettestresult(ESYS_CONTEXT *ectx, TPM2B_MAX_BUFFER **out_data, TPM2_RC *test_result) { TSS2_RC rval = Esys_GetTestResult(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, out_data, test_result); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_GetTestResult, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_loadexternal(ESYS_CONTEXT *ectx, const TPM2B_SENSITIVE *private, const TPM2B_PUBLIC *public, TPMI_RH_HIERARCHY hierarchy, ESYS_TR *object_handle) { TSS2_RC rval = fix_esys_hierarchy(hierarchy, &hierarchy); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } rval = Esys_LoadExternal(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, private, public, hierarchy, object_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_LoadExternal, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_pcr_event(ESYS_CONTEXT *ectx, ESYS_TR pcr, tpm2_session *session, const TPM2B_EVENT *event_data, TPML_DIGEST_VALUES **digests) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, pcr, session, &shandle1); if (rc != tool_rc_success) { return rc; } TSS2_RC rval = Esys_PCR_Event(ectx, pcr, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, event_data, digests); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PCR_Event, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_getrandom(ESYS_CONTEXT *ectx, UINT16 count, TPM2B_DIGEST **random, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, ESYS_TR session_handle_1, ESYS_TR session_handle_2, ESYS_TR session_handle_3, TPMI_ALG_HASH parameter_hash_algorithm) { TSS2_SYS_CONTEXT *sys_context = NULL; tool_rc rc = tool_rc_success; if (cp_hash->size || rp_hash->size) { rc = tpm2_getsapicontext(ectx, &sys_context); if (rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } } if (cp_hash->size) { TSS2_RC rval = Tss2_Sys_GetRandom_Prepare(sys_context, count); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetRandom_Prepare, rval); return tool_rc_general_error; } rc = tpm2_sapi_getcphash(sys_context, NULL, NULL, NULL, parameter_hash_algorithm, cp_hash); if (rc != tool_rc_success) { return rc; } /* * Exit here without making the ESYS call since if we only need cpHash */ if (!rp_hash->size || rc != tool_rc_success) { goto tpm2_getrandom_skip_esapi_call; } } TSS2_RC rval = Esys_GetRandom(ectx, session_handle_1, session_handle_2, session_handle_3, count, random); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_GetRandom, rval); return tool_rc_from_tpm(rval); } if (rp_hash->size) { rc = tpm2_sapi_getrphash(sys_context, rval, rp_hash, parameter_hash_algorithm); } tpm2_getrandom_skip_esapi_call: return rc; } tool_rc tpm2_startup(ESYS_CONTEXT *ectx, TPM2_SU startup_type) { TSS2_RC rval = Esys_Startup(ectx, startup_type); if (rval != TPM2_RC_SUCCESS && rval != TPM2_RC_INITIALIZE) { LOG_PERR(Esys_Startup, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_pcr_reset(ESYS_CONTEXT *ectx, ESYS_TR pcr_handle) { TSS2_RC rval = Esys_PCR_Reset(ectx, pcr_handle, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_PCR_Reset, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_makecredential(ESYS_CONTEXT *ectx, ESYS_TR handle, const TPM2B_DIGEST *credential, const TPM2B_NAME *object_name, TPM2B_ID_OBJECT **credential_blob, TPM2B_ENCRYPTED_SECRET **secret) { TSS2_RC rval = Esys_MakeCredential(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, credential, object_name, credential_blob, secret); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_MakeCredential, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_verifysignature(ESYS_CONTEXT *ectx, ESYS_TR key_handle, const TPM2B_DIGEST *digest, const TPMT_SIGNATURE *signature, TPMT_TK_VERIFIED **validation) { TSS2_RC rval = Esys_VerifySignature(ectx, key_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, digest, signature, validation); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_VerifySignature, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_readclock(ESYS_CONTEXT *ectx, TPMS_TIME_INFO **current_time) { TSS2_RC rval = Esys_ReadClock(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, current_time); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ReadClock, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_setclock(ESYS_CONTEXT *ectx, tpm2_loaded_object *object, UINT64 new_time, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, object->tr_handle, object->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for lockout hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_ClockSet_Prepare(sys_context, object->handle, new_time); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ClockSet_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, object->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_setclock_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(object->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(object->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_setclock_free_name1: Esys_Free(name1); goto tpm2_setclock_skip_esapi_call; } TSS2_RC rval = Esys_ClockSet(ectx, object->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, new_time); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ClockSet, rval); return tool_rc_from_tpm(rval); } tpm2_setclock_skip_esapi_call: return rc; } tool_rc tpm2_clockrateadjust(ESYS_CONTEXT *ectx, tpm2_loaded_object *object, TPM2_CLOCK_ADJUST rate_adjust, TPM2B_DIGEST *cp_hash) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, object->tr_handle, object->session, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for lockout hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_ClockRateAdjust_Prepare(sys_context, object->handle, rate_adjust); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_ClockRateAdjust_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, object->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_clockrateadjust_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(object->session)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(object->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_clockrateadjust_free_name1: Esys_Free(name1); goto tpm2_clockrateadjust_skip_esapi_call; } TSS2_RC rval = Esys_ClockRateAdjust(ectx, object->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, rate_adjust); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_ClockRateAdjust, rval); return tool_rc_from_tpm(rval); } tpm2_clockrateadjust_skip_esapi_call: return rc; } tool_rc tpm2_shutdown(ESYS_CONTEXT *ectx, TPM2_SU shutdown_type) { TSS2_RC rval = Esys_Shutdown(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, shutdown_type); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Shutdown, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_gettime(ESYS_CONTEXT *ectx, tpm2_loaded_object *privacy_admin, tpm2_loaded_object *signing_object, const TPM2B_DATA *qualifying_data, const TPMT_SIG_SCHEME *scheme, TPM2B_ATTEST **time_info, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash) { ESYS_TR privacy_admin_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, privacy_admin->tr_handle, privacy_admin->session, &privacy_admin_session_handle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for privacy admin"); return rc; } ESYS_TR sign_session_handle = ESYS_TR_NONE; rc = tpm2_auth_util_get_shandle(ectx, signing_object->tr_handle, signing_object->session, &sign_session_handle); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for signing key"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_GetTime_Prepare(sys_context, privacy_admin->handle, signing_object->handle, qualifying_data, scheme); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetTime_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, privacy_admin->tr_handle, &name1); if (rc != tool_rc_success) { goto tpm2_gettime_free_name1; } TPM2B_NAME *name2 = NULL; rc = tpm2_tr_get_name(ectx, signing_object->tr_handle, &name2); if (rc != tool_rc_success) { goto tpm2_gettime_free_name1_name2; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(signing_object->session)); rc = tpm2_sapi_getcphash(sys_context, name1, name2, NULL, tpm2_session_get_authhash(signing_object->session), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_gettime_free_name1_name2: Esys_Free(name2); tpm2_gettime_free_name1: Esys_Free(name1); goto tpm2_gettime_skip_esapi_call; } TSS2_RC rval = Esys_GetTime( ectx, privacy_admin->tr_handle, signing_object->tr_handle, privacy_admin_session_handle, sign_session_handle, ESYS_TR_NONE, qualifying_data, scheme, time_info, signature); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_GetTime, rval); return tool_rc_from_tpm(rval); } tpm2_gettime_skip_esapi_call: return rc; } tool_rc tpm2_geteccparameters(ESYS_CONTEXT *esys_context, TPMI_ECC_CURVE curve_id, TPMS_ALGORITHM_DETAIL_ECC **parameters) { TSS2_RC rval = Esys_ECC_Parameters(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, curve_id, parameters); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ECC_Parameters, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_ecephemeral(ESYS_CONTEXT *esys_context, TPMI_ECC_CURVE curve_id, TPM2B_ECC_POINT **Q, uint16_t *counter) { TSS2_RC rval = Esys_EC_Ephemeral(esys_context, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, curve_id, Q, counter); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_EC_Ephemeral, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_commit(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signing_key_object, TPM2B_ECC_POINT *P1, TPM2B_SENSITIVE_DATA *s2, TPM2B_ECC_PARAMETER *y2, TPM2B_ECC_POINT **K, TPM2B_ECC_POINT **L, TPM2B_ECC_POINT **E, uint16_t *counter) { ESYS_TR signing_key_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, signing_key_object->tr_handle, signing_key_object->session, &signing_key_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } TSS2_RC rval = Esys_Commit(esys_context, signing_key_object->tr_handle, signing_key_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, P1, s2, y2, K, L, E, counter); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_Commit, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_ecdhkeygen(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_public_key, TPM2B_ECC_POINT **Z, TPM2B_ECC_POINT **Q) { TSS2_RC rval = Esys_ECDH_KeyGen(esys_context, ecc_public_key->tr_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, Z, Q); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ECDH_KeyGen, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_ecdhzgen(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_key_object, TPM2B_ECC_POINT **Z, TPM2B_ECC_POINT *Q) { ESYS_TR ecc_key_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, ecc_key_object->tr_handle, ecc_key_object->session, &ecc_key_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } TSS2_RC rval = Esys_ECDH_ZGen(esys_context, ecc_key_object->tr_handle, ecc_key_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, Q, Z); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ECDH_ZGen, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_zgen2phase(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_key_object, TPM2B_ECC_POINT *Q1, TPM2B_ECC_POINT *Q2, TPM2B_ECC_POINT **Z1, TPM2B_ECC_POINT **Z2, TPMI_ECC_KEY_EXCHANGE keyexchange_scheme, UINT16 commit_counter) { ESYS_TR ecc_key_obj_session_handle = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(esys_context, ecc_key_object->tr_handle, ecc_key_object->session, &ecc_key_obj_session_handle); if (rc != tool_rc_success) { LOG_ERR("Failed to get shandle"); return rc; } TSS2_RC rval = Esys_ZGen_2Phase(esys_context, ecc_key_object->tr_handle, ecc_key_obj_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, Q1, Q2, keyexchange_scheme, commit_counter, Z1, Z2); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_ZGen_2Phase, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_getsapicontext(ESYS_CONTEXT *esys_context, TSS2_SYS_CONTEXT **sys_context) { TSS2_RC rval = Esys_GetSysContext(esys_context, sys_context); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_GetSysContext, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } tool_rc tpm2_sapi_getrphash(TSS2_SYS_CONTEXT *sys_context, TSS2_RC response_code, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH halg) { uint8_t command_code[4]; TSS2_RC rval = Tss2_Sys_GetCommandCode(sys_context, &command_code[0]); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetCommandCode, rval); return tool_rc_general_error; } const uint8_t *response_parameters; size_t response_parameters_size; rval = Tss2_Sys_GetRpBuffer(sys_context, &response_parameters_size, &response_parameters); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetRpBuffer, rval); return tool_rc_general_error; } uint16_t to_hash_len = sizeof(response_code) + sizeof(command_code) + response_parameters_size; uint8_t *to_hash = malloc(to_hash_len); if (!to_hash) { LOG_ERR("oom"); return tool_rc_general_error; } //Response-Code memcpy(to_hash, (uint8_t *)&response_code, sizeof(response_code)); uint16_t offset = sizeof(response_code); //Command-Code memcpy(to_hash + offset, command_code, sizeof(command_code)); offset += sizeof(command_code); //RpBuffer memcpy(to_hash + offset, response_parameters, response_parameters_size); //rpHash tool_rc rc = tool_rc_success; bool result = tpm2_openssl_hash_compute_data(halg, to_hash, to_hash_len, rp_hash); free(to_hash); if (!result) { LOG_ERR("Failed rpHash digest calculation."); rc = tool_rc_general_error; } return rc; } tool_rc tpm2_sapi_getcphash(TSS2_SYS_CONTEXT *sys_context, const TPM2B_NAME *name1, const TPM2B_NAME *name2, const TPM2B_NAME *name3, TPMI_ALG_HASH halg, TPM2B_DIGEST *cp_hash) { uint8_t command_code[4]; TSS2_RC rval = Tss2_Sys_GetCommandCode(sys_context, &command_code[0]); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetCommandCode, rval); return tool_rc_general_error; } const uint8_t *command_parameters; size_t command_parameters_size; rval = Tss2_Sys_GetCpBuffer(sys_context, &command_parameters_size, &command_parameters); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_GetCpBuffer, rval); return tool_rc_general_error; } uint16_t to_hash_len = sizeof(command_code) + command_parameters_size; to_hash_len += name1 ? name1->size : 0; to_hash_len += name2 ? name2->size : 0; to_hash_len += name3 ? name3->size : 0; uint8_t *to_hash = malloc(to_hash_len); if (!to_hash) { LOG_ERR("oom"); return tool_rc_general_error; } //Command-Code memcpy(to_hash, command_code, sizeof(command_code)); uint16_t offset = sizeof(command_code); //Names if (name1) { memcpy(to_hash + offset, name1->name, name1->size); offset += name1->size; } if (name2) { memcpy(to_hash + offset, name2->name, name2->size); offset += name2->size; } if (name3) { memcpy(to_hash + offset, name3->name, name3->size); offset += name3->size; } //CpBuffer memcpy(to_hash + offset, command_parameters, command_parameters_size); //cpHash tool_rc rc = tool_rc_success; bool result = tpm2_openssl_hash_compute_data(halg, to_hash, to_hash_len, cp_hash); free(to_hash); if (!result) { LOG_ERR("Failed cpHash digest calculation."); rc = tool_rc_general_error; } return rc; } tpm2-tools-5.2/lib/tpm2.h000066400000000000000000000563171412464516500152250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_H_ #define LIB_TPM2_H_ #include #include "object.h" #include "tool_rc.h" tool_rc tpm2_from_tpm_public(ESYS_CONTEXT *esys_context, TPM2_HANDLE tpm_handle, ESYS_TR optional_session1, ESYS_TR optional_session2, ESYS_TR optional_session3, ESYS_TR *object); tool_rc tpm2_close(ESYS_CONTEXT *esys_context, ESYS_TR *rsrc_handle); tool_rc tpm2_tr_deserialize(ESYS_CONTEXT *esys_context, uint8_t const *buffer, size_t buffer_size, ESYS_TR *esys_handle); tool_rc tpm2_tr_serialize(ESYS_CONTEXT *esys_context, ESYS_TR object, uint8_t **buffer, size_t *buffer_size); tool_rc tpm2_nv_readpublic(ESYS_CONTEXT *esys_context, ESYS_TR nv_index, TPM2B_NV_PUBLIC **nv_public, TPM2B_NAME **nv_name); tool_rc tpm2_readpublic(ESYS_CONTEXT *esys_context, ESYS_TR object_handle, TPM2B_PUBLIC **out_public, TPM2B_NAME **name, TPM2B_NAME **qualified_name); tool_rc tpm2_getcap(ESYS_CONTEXT *esys_context,TPM2_CAP capability, UINT32 property, UINT32 property_count, TPMI_YES_NO *more_data, TPMS_CAPABILITY_DATA **capability_data); tool_rc tpm2_nv_read(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_NAME *precalc_nvname, UINT16 size, UINT16 offset, TPM2B_MAX_NV_BUFFER **data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_context_save(ESYS_CONTEXT *esys_context, ESYS_TR save_handle, TPMS_CONTEXT **context); tool_rc tpm2_context_load(ESYS_CONTEXT *esys_context, const TPMS_CONTEXT *context, ESYS_TR *loaded_handle); tool_rc tpm2_flush_context(ESYS_CONTEXT *esys_context, ESYS_TR flush_handle); tool_rc tpm2_start_auth_session(ESYS_CONTEXT *esys_context, ESYS_TR tpm_key, ESYS_TR bind, const TPM2B_NONCE *nonce_caller, TPM2_SE session_type, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH auth_hash, ESYS_TR *session_handle); tool_rc tpm2_sess_set_attributes(ESYS_CONTEXT *esys_context, ESYS_TR session, TPMA_SESSION flags, TPMA_SESSION mask); tool_rc tpm2_sess_get_attributes(ESYS_CONTEXT *esys_context, ESYS_TR session, TPMA_SESSION *flags); tool_rc tpm2_sess_get_noncetpm(ESYS_CONTEXT *esys_context, ESYS_TR session_handle, TPM2B_NONCE **nonce_tpm); tool_rc tpm2_policy_restart(ESYS_CONTEXT *esys_context, ESYS_TR session_handle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_get_capability(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CAP capability, UINT32 property, UINT32 property_count, TPMI_YES_NO *more_data, TPMS_CAPABILITY_DATA **capability_data); tool_rc tpm2_create_primary(ESYS_CONTEXT *esys_context, ESYS_TR primary_handle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_PUBLIC *in_public, const TPM2B_DATA *outside_info, const TPML_PCR_SELECTION *creation_pcr, ESYS_TR *object_handle, TPM2B_PUBLIC **out_public, TPM2B_CREATION_DATA **creation_data, TPM2B_DIGEST **creation_hash, TPMT_TK_CREATION **creation_ticket); tool_rc tpm2_pcr_read(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcr_selection_in, UINT32 *pcr_update_counter, TPML_PCR_SELECTION **pcr_selection_out, TPML_DIGEST **pcr_values); tool_rc tpm2_policy_authorize(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *approved_policy, const TPM2B_NONCE *policy_ref, const TPM2B_NAME *key_sign, const TPMT_TK_VERIFIED *check_ticket); tool_rc tpm2_policy_or(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_DIGEST *p_hash_list); tool_rc tpm2_policy_namehash(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *name_hash); tool_rc tpm2_policy_template(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *template_hash); tool_rc tpm2_policy_cphash(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_DIGEST *cphash); tool_rc tpm2_policy_pcr(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcr_digest, const TPML_PCR_SELECTION *pcrs); tool_rc tpm2_policy_password(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_policy_signed(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, ESYS_TR policy_session, const TPMT_SIGNATURE *signature, INT32 expiration, TPM2B_TIMEOUT **timeout, TPMT_TK_AUTH **policy_ticket, TPM2B_NONCE *policy_qualifier, TPM2B_NONCE *nonce_tpm, TPM2B_DIGEST *cphash); tool_rc tpm2_policy_ticket(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_TIMEOUT *timeout, const TPM2B_NONCE *policyref, const TPM2B_NAME *authname, const TPMT_TK_AUTH *ticket); tool_rc tpm2_policy_authvalue(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_policy_secret(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, ESYS_TR policy_session, INT32 expiration, TPMT_TK_AUTH **policy_ticket, TPM2B_TIMEOUT **timeout, TPM2B_NONCE *nonce_tpm, TPM2B_NONCE *policy_qualifier, TPM2B_DIGEST *cp_hash); tool_rc tpm2_policy_getdigest(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policy_digest); tool_rc tpm2_policy_command_code(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2_CC code); tool_rc tpm2_policy_locality(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMA_LOCALITY locality); tool_rc tpm2_policy_duplication_select(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NAME *object_name, const TPM2B_NAME *new_parent_name, TPMI_YES_NO include_object); tool_rc tpm2_tr_get_name(ESYS_CONTEXT *esys_context, ESYS_TR handle, TPM2B_NAME **name); tool_rc tpm2_mu_tpm2_handle_unmarshal(uint8_t const buffer[], size_t size, size_t *offset, TPM2_HANDLE *out); tool_rc tpm2_mu_tpmt_public_marshal(TPMT_PUBLIC const *src, uint8_t buffer[], size_t buffer_size, size_t *offset); tool_rc tpm2_evictcontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, tpm2_loaded_object *to_persist_key_obj, TPMI_DH_PERSISTENT persistent_handle, ESYS_TR *new_object_handle, TPM2B_DIGEST *cp_hash); tool_rc tpm2_hash(ESYS_CONTEXT *esys_context, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_MAX_BUFFER *data, TPMI_ALG_HASH hash_alg, TPMI_RH_HIERARCHY hierarchy, TPM2B_DIGEST **out_hash, TPMT_TK_HASHCHECK **validation); tool_rc tpm2_hash_sequence_start(ESYS_CONTEXT *esys_context, const TPM2B_AUTH *auth, TPMI_ALG_HASH hash_alg, ESYS_TR *sequence_handle); tool_rc tpm2_sequence_update(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, const TPM2B_MAX_BUFFER *buffer); tool_rc tpm2_sequence_complete(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, const TPM2B_MAX_BUFFER *buffer, TPMI_RH_HIERARCHY hierarchy, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation); tool_rc tpm2_event_sequence_complete(ESYS_CONTEXT *ectx, ESYS_TR pcr, ESYS_TR sequence_handle, tpm2_session *session, const TPM2B_MAX_BUFFER *buffer, TPML_DIGEST_VALUES **results); tool_rc tpm2_tr_set_auth(ESYS_CONTEXT *esys_context, ESYS_TR handle, TPM2B_AUTH const *auth_value); tool_rc tpm2_activatecredential(ESYS_CONTEXT *esys_context, tpm2_loaded_object *activatehandle, tpm2_loaded_object *keyhandle, const TPM2B_ID_OBJECT *credential_blob, const TPM2B_ENCRYPTED_SECRET *secret, TPM2B_DIGEST **cert_info, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle3); tool_rc tpm2_create(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_PUBLIC *in_public, const TPM2B_DATA *outside_info, const TPML_PCR_SELECTION *creation_pcr, TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public, TPM2B_CREATION_DATA **creation_data, TPM2B_DIGEST **creation_hash, TPMT_TK_CREATION **creation_ticket, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_create_loaded(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_SENSITIVE_CREATE *in_sensitive, const TPM2B_TEMPLATE *in_public, ESYS_TR *object_handle, TPM2B_PRIVATE **out_private, TPM2B_PUBLIC **out_public, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_object_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_object, tpm2_loaded_object *object, const TPM2B_AUTH *new_auth, TPM2B_PRIVATE **out_private, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_nv_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *nv, const TPM2B_AUTH *new_auth, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_hierarchy_change_auth(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hierarchy, const TPM2B_AUTH *new_auth, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_certify(ESYS_CONTEXT *esys_context, tpm2_loaded_object *certifiedkey_obj, tpm2_loaded_object *signingkey_obj, TPM2B_DATA *qualifying_data, TPMT_SIG_SCHEME *scheme, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle3); tool_rc tpm2_rsa_decrypt(ESYS_CONTEXT *esys_context, tpm2_loaded_object *keyobj, const TPM2B_PUBLIC_KEY_RSA *cipher_text, const TPMT_RSA_DECRYPT *in_scheme, const TPM2B_DATA *label, TPM2B_PUBLIC_KEY_RSA **message, TPM2B_DIGEST *cp_hash); tool_rc tpm2_rsa_encrypt(ESYS_CONTEXT *ectx, tpm2_loaded_object *keyobj, const TPM2B_PUBLIC_KEY_RSA *message, const TPMT_RSA_DECRYPT *scheme, const TPM2B_DATA *label, TPM2B_PUBLIC_KEY_RSA **cipher_text); tool_rc tpm2_load(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parentobj, const TPM2B_PRIVATE *in_private, const TPM2B_PUBLIC *in_public, ESYS_TR *object_handle, TPM2B_DIGEST *cp_hash); tool_rc tpm2_clear(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPM2B_DIGEST *cp_hash); tool_rc tpm2_clearcontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPMI_YES_NO disable_clear, TPM2B_DIGEST *cp_hash); tool_rc tpm2_clockrateadjust(ESYS_CONTEXT *ectx, tpm2_loaded_object *object, TPM2_CLOCK_ADJUST rate_adjust, TPM2B_DIGEST *cp_hash); tool_rc tpm2_dictionarylockout_reset(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPM2B_DIGEST *cp_hash); tool_rc tpm2_dictionarylockout_setup(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, UINT32 max_tries, UINT32 recovery_time, UINT32 lockout_recovery_time, TPM2B_DIGEST *cp_hash); tool_rc tpm2_duplicate(ESYS_CONTEXT *esys_context, tpm2_loaded_object *duplicable_key, tpm2_loaded_object *new_parent_handle, const TPM2B_DATA *in_key, const TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_DATA **out_key, TPM2B_PRIVATE **duplicate, TPM2B_ENCRYPTED_SECRET **encrypted_seed, TPM2B_DIGEST *cp_hash); tool_rc tpm2_encryptdecrypt(ESYS_CONTEXT *esys_context, tpm2_loaded_object *encryption_key_obj, TPMI_YES_NO decrypt, TPMI_ALG_SYM_MODE mode, const TPM2B_IV *iv_in, const TPM2B_MAX_BUFFER *input_data, TPM2B_MAX_BUFFER **output_data, TPM2B_IV **iv_out, TPM2B_DIGEST *cp_hash); tool_rc tpm2_hierarchycontrol(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy, TPMI_RH_ENABLES enable, TPMI_YES_NO state, TPM2B_DIGEST *cp_hash); tool_rc tpm2_hmac(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hmac_key_obj, TPMI_ALG_HASH halg, const TPM2B_MAX_BUFFER *input_buffer, TPM2B_DIGEST **out_hmac, TPM2B_DIGEST *cp_hash); tool_rc tpm2_hmac_start(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hmac_key_obj, TPMI_ALG_HASH halg, ESYS_TR *sequence_handle); tool_rc tpm2_hmac_sequenceupdate(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, tpm2_loaded_object *hmac_key_obj, const TPM2B_MAX_BUFFER *input_buffer); tool_rc tpm2_hmac_sequencecomplete(ESYS_CONTEXT *esys_context, ESYS_TR sequence_handle, tpm2_loaded_object *hmac_key_obj, const TPM2B_MAX_BUFFER *input_buffer, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation); tool_rc tpm2_import(ESYS_CONTEXT *esys_context, tpm2_loaded_object *parent_obj, const TPM2B_DATA *encryption_key, const TPM2B_PUBLIC *object_public, const TPM2B_PRIVATE *duplicate, const TPM2B_ENCRYPTED_SECRET *in_sym_seed, const TPMT_SYM_DEF_OBJECT *symmetric_alg, TPM2B_PRIVATE **out_private, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nv_definespace(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, const TPM2B_AUTH *auth, const TPM2B_NV_PUBLIC *public_info, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_nvextend(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_MAX_NV_BUFFER *data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, TPM2B_NAME *precalc_nvname, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_nv_increment(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nvreadlock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nvglobalwritelock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nvwritelock(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash); tool_rc tpm2_tr_from_tpm_public(ESYS_CONTEXT *esys_context, TPM2_HANDLE handle, ESYS_TR *tr_handle); tool_rc tpm2_nvsetbits(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, UINT64 bits, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, TPM2B_NAME *precalc_nvname, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_nvundefine(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nvundefinespecial(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nv_index, tpm2_session *policy_session, TPM2B_DIGEST *cp_hash); tool_rc tpm2_nvwrite(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, TPM2_HANDLE nvindex, const TPM2B_MAX_NV_BUFFER *data, UINT16 offset, TPM2B_DIGEST *cp_hash); tool_rc tpm2_pcr_allocate(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_hierarchy_obj, const TPML_PCR_SELECTION *pcr_allocation); tool_rc tpm2_sign(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, TPM2B_DIGEST *digest, TPMT_SIG_SCHEME *in_scheme, TPMT_TK_HASHCHECK *validation, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash); tool_rc tpm2_quote(ESYS_CONTEXT *esys_context, tpm2_loaded_object *quote_obj, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPML_PCR_SELECTION *PCRselect, TPM2B_ATTEST **quoted, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash); tool_rc tpm2_changeeps(ESYS_CONTEXT *ectx, tpm2_session *platform_hierarchy_session, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_changepps(ESYS_CONTEXT *ectx, tpm2_session *platform_hierarchy_session, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_unseal(ESYS_CONTEXT *esys_context, tpm2_loaded_object *sealkey_obj, TPM2B_SENSITIVE_DATA **out_data, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_policy_authorize_nv(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, TPM2_HANDLE nv_index, ESYS_TR policy_session, TPM2B_DIGEST *cp_hash); tool_rc tpm2_incrementalselftest(ESYS_CONTEXT *ectx, const TPML_ALG *to_test, TPML_ALG **to_do_list); tool_rc tpm2_stirrandom(ESYS_CONTEXT *ectx, const TPM2B_SENSITIVE_DATA *data); tool_rc tpm2_selftest(ESYS_CONTEXT *ectx, TPMI_YES_NO full_test); tool_rc tpm2_gettestresult(ESYS_CONTEXT *ectx, TPM2B_MAX_BUFFER **out_data, TPM2_RC *test_result); tool_rc tpm2_loadexternal(ESYS_CONTEXT *ectx, const TPM2B_SENSITIVE *private, const TPM2B_PUBLIC *public, TPMI_RH_HIERARCHY hierarchy, ESYS_TR *object_handle); tool_rc tpm2_pcr_event(ESYS_CONTEXT *ectx, ESYS_TR pcr, tpm2_session *session, const TPM2B_EVENT *event_data, TPML_DIGEST_VALUES **digests); tool_rc tpm2_getrandom(ESYS_CONTEXT *ectx, UINT16 count, TPM2B_DIGEST **random, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, ESYS_TR session_handle_1, ESYS_TR session_handle_2, ESYS_TR session_handle_3, TPMI_ALG_HASH param_hash_algorithm) ; tool_rc tpm2_startup(ESYS_CONTEXT *ectx, TPM2_SU startup_type); tool_rc tpm2_pcr_reset(ESYS_CONTEXT *ectx, ESYS_TR pcr_handle); tool_rc tpm2_makecredential(ESYS_CONTEXT *ectx, ESYS_TR handle, const TPM2B_DIGEST *credential, const TPM2B_NAME *object_name, TPM2B_ID_OBJECT **credential_blob, TPM2B_ENCRYPTED_SECRET **secret); tool_rc tpm2_verifysignature(ESYS_CONTEXT *ectx, ESYS_TR key_handle, const TPM2B_DIGEST *digest, const TPMT_SIGNATURE *signature, TPMT_TK_VERIFIED **validation); tool_rc tpm2_readclock(ESYS_CONTEXT *ectx, TPMS_TIME_INFO **current_time); tool_rc tpm2_setclock(ESYS_CONTEXT *ectx, tpm2_loaded_object *object, UINT64 new_time, TPM2B_DIGEST *cp_hash); tool_rc tpm2_shutdown(ESYS_CONTEXT *ectx, TPM2_SU shutdown_type); tool_rc tpm2_policy_nv(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, TPM2_HANDLE nv_index, ESYS_TR policy_session, const TPM2B_OPERAND *operand_b, UINT16 offset, TPM2_EO operation, TPM2B_DIGEST *cp_hash); tool_rc tpm2_policy_countertimer(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, const TPM2B_OPERAND *operand_b, UINT16 offset, TPM2_EO operation); tool_rc tpm2_policy_nv_written(ESYS_CONTEXT *esys_context, ESYS_TR policy_session, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPMI_YES_NO written_set); TSS2_RC fix_esys_hierarchy(uint32_t in, uint32_t *out); tool_rc tpm2_certifycreation(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, tpm2_loaded_object *certifiedkey_obj, TPM2B_DIGEST *creation_hash, TPMT_SIG_SCHEME *in_scheme, TPMT_TK_CREATION *creation_ticket, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DATA *policy_qualifier, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, ESYS_TR shandle2, ESYS_TR shandle3); tool_rc tpm2_nvcertify(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signingkey_obj, tpm2_loaded_object *nvindex_authobj, TPM2_HANDLE nv_index, UINT16 offset, UINT16 size, TPMT_SIG_SCHEME *in_scheme, TPM2B_ATTEST **certify_info, TPMT_SIGNATURE **signature, TPM2B_DATA *policy_qualifier, TPM2B_DIGEST *cp_hash); tool_rc tpm2_setprimarypolicy(ESYS_CONTEXT *esys_context, tpm2_loaded_object *hierarchy_object, TPM2B_DIGEST *auth_policy, TPMI_ALG_HASH hash_algorithm, TPM2B_DIGEST *cp_hash); tool_rc tpm2_gettime(ESYS_CONTEXT *ectx, tpm2_loaded_object *privacy_admin, tpm2_loaded_object *signing_object, const TPM2B_DATA *qualifying_data, const TPMT_SIG_SCHEME *scheme, TPM2B_ATTEST **time_info, TPMT_SIGNATURE **signature, TPM2B_DIGEST *cp_hash); tool_rc tpm2_setcommandcodeaudit(ESYS_CONTEXT *esys_context, tpm2_loaded_object *auth_entity_obj, TPMI_ALG_HASH hash_algorithm, const TPML_CC *setlist, const TPML_CC *clearlist); tool_rc tpm2_getcommandauditdigest(ESYS_CONTEXT *esys_context, tpm2_loaded_object *privacy_object, tpm2_loaded_object *sign_object, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPM2B_ATTEST **audit_info, TPMT_SIGNATURE **signature); tool_rc tpm2_getsessionauditdigest(ESYS_CONTEXT *esys_context, tpm2_loaded_object *privacy_object, tpm2_loaded_object *sign_object, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *qualifying_data, TPM2B_ATTEST **audit_info, TPMT_SIGNATURE **signature, ESYS_TR audit_session_handle); tool_rc tpm2_geteccparameters(ESYS_CONTEXT *esys_context, TPMI_ECC_CURVE curve_id, TPMS_ALGORITHM_DETAIL_ECC **parameters); tool_rc tpm2_ecephemeral(ESYS_CONTEXT *esys_context, TPMI_ECC_CURVE curve_id, TPM2B_ECC_POINT **Q, uint16_t *counter); tool_rc tpm2_commit(ESYS_CONTEXT *esys_context, tpm2_loaded_object *signing_key_object, TPM2B_ECC_POINT *P1, TPM2B_SENSITIVE_DATA *s2, TPM2B_ECC_PARAMETER *y2, TPM2B_ECC_POINT **K, TPM2B_ECC_POINT **L, TPM2B_ECC_POINT **E, uint16_t *counter); tool_rc tpm2_ecdhkeygen(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_public_key, TPM2B_ECC_POINT **Z, TPM2B_ECC_POINT **Q); tool_rc tpm2_ecdhzgen(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_key_object, TPM2B_ECC_POINT **Z, TPM2B_ECC_POINT *Q); tool_rc tpm2_zgen2phase(ESYS_CONTEXT *esys_context, tpm2_loaded_object *ecc_key_object, TPM2B_ECC_POINT *Q1, TPM2B_ECC_POINT *Q2, TPM2B_ECC_POINT **Z1, TPM2B_ECC_POINT **Z2, TPMI_ECC_KEY_EXCHANGE keyexchange_scheme, UINT16 commit_counter); tool_rc tpm2_getsapicontext(ESYS_CONTEXT *esys_context, TSS2_SYS_CONTEXT **sys_context); tool_rc tpm2_sapi_getcphash(TSS2_SYS_CONTEXT *sys_context, const TPM2B_NAME *name1, const TPM2B_NAME *name2, const TPM2B_NAME *name3, TPMI_ALG_HASH halg, TPM2B_DIGEST *cp_hash); tool_rc tpm2_sapi_getrphash(TSS2_SYS_CONTEXT *sys_context, TSS2_RC response_code, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH halg); #endif /* LIB_TPM2_H_ */ tpm2-tools-5.2/lib/tpm2_alg_util.c000066400000000000000000001022201412464516500170610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_errata.h" typedef struct alg_pair alg_pair; struct alg_pair { const char *name; TPM2_ALG_ID id; tpm2_alg_util_flags flags; tpm2_alg_util_flags _flags; }; typedef enum alg_iter_res alg_iter_res; enum alg_iter_res { stop, go, found }; typedef enum alg_parser_rc alg_parser_rc; enum alg_parser_rc { alg_parser_rc_error, alg_parser_rc_continue, alg_parser_rc_done }; typedef alg_iter_res (*alg_iter)(TPM2_ALG_ID id, const char *name, tpm2_alg_util_flags flags, void *userdata); static void tpm2_alg_util_for_each_alg(alg_iter iterator, void *userdata) { static const alg_pair algs[] = { // Assymetric { .name = "rsa", .id = TPM2_ALG_RSA, .flags = tpm2_alg_util_flags_asymmetric|tpm2_alg_util_flags_base }, { .name = "ecc", .id = TPM2_ALG_ECC, .flags = tpm2_alg_util_flags_asymmetric|tpm2_alg_util_flags_base }, // Symmetric { .name = "tdes", .id = TPM2_ALG_TDES, .flags = tpm2_alg_util_flags_symmetric }, { .name = "aes", .id = TPM2_ALG_AES, .flags = tpm2_alg_util_flags_symmetric }, { .name = "camellia", .id = TPM2_ALG_CAMELLIA, .flags = tpm2_alg_util_flags_symmetric }, // Hash { .name = "sha1", .id = TPM2_ALG_SHA1, .flags = tpm2_alg_util_flags_hash }, { .name = "sha256", .id = TPM2_ALG_SHA256, .flags = tpm2_alg_util_flags_hash }, { .name = "sha384", .id = TPM2_ALG_SHA384, .flags = tpm2_alg_util_flags_hash }, { .name = "sha512", .id = TPM2_ALG_SHA512, .flags = tpm2_alg_util_flags_hash }, { .name = "sm3_256", .id = TPM2_ALG_SM3_256, .flags = tpm2_alg_util_flags_hash }, { .name = "sha3_256", .id = TPM2_ALG_SHA3_256, .flags = tpm2_alg_util_flags_hash }, { .name = "sha3_384", .id = TPM2_ALG_SHA3_384, .flags = tpm2_alg_util_flags_hash }, { .name = "sha3_512", .id = TPM2_ALG_SHA3_512, .flags = tpm2_alg_util_flags_hash }, // Keyed hash { .name = "hmac", .id = TPM2_ALG_HMAC, tpm2_alg_util_flags_keyedhash | tpm2_alg_util_flags_sig }, { .name = "xor", .id = TPM2_ALG_XOR, tpm2_alg_util_flags_keyedhash }, { .name = "cmac", .id = TPM2_ALG_CMAC, .flags = tpm2_alg_util_flags_sig }, // Mask Generation Functions { .name = "mgf1", .id = TPM2_ALG_MGF1, .flags = tpm2_alg_util_flags_mgf }, // Signature Schemes { .name = "rsassa", .id = TPM2_ALG_RSASSA, .flags = tpm2_alg_util_flags_sig }, { .name = "rsapss", .id = TPM2_ALG_RSAPSS, .flags = tpm2_alg_util_flags_sig }, { .name = "ecdsa", .id = TPM2_ALG_ECDSA, .flags = tpm2_alg_util_flags_sig }, { .name = "ecdaa", .id = TPM2_ALG_ECDAA, .flags = tpm2_alg_util_flags_sig }, { .name = "ecschnorr", .id = TPM2_ALG_ECSCHNORR, .flags = tpm2_alg_util_flags_sig }, // Assyemtric Encryption Scheme { .name = "oaep", .id = TPM2_ALG_OAEP, .flags = tpm2_alg_util_flags_enc_scheme | tpm2_alg_util_flags_rsa_scheme }, { .name = "rsaes", .id = TPM2_ALG_RSAES, .flags = tpm2_alg_util_flags_enc_scheme | tpm2_alg_util_flags_rsa_scheme }, { .name = "ecdh", .id = TPM2_ALG_ECDH, .flags = tpm2_alg_util_flags_enc_scheme }, // XXX are these sigs? { .name = "sm2", .id = TPM2_ALG_SM2, .flags = tpm2_alg_util_flags_sig }, { .name = "sm4", .id = TPM2_ALG_SM4, .flags = tpm2_alg_util_flags_sig }, // Key derivation functions { .name = "kdf1_sp800_56a", .id = TPM2_ALG_KDF1_SP800_56A, .flags = tpm2_alg_util_flags_kdf }, { .name = "kdf2", .id = TPM2_ALG_KDF2, .flags = tpm2_alg_util_flags_kdf }, { .name = "kdf1_sp800_108", .id = TPM2_ALG_KDF1_SP800_108, .flags = tpm2_alg_util_flags_kdf }, { .name = "ecmqv", .id = TPM2_ALG_ECMQV, .flags = tpm2_alg_util_flags_kdf }, // Modes { .name = "ctr", .id = TPM2_ALG_CTR, .flags = tpm2_alg_util_flags_mode }, { .name = "ofb", .id = TPM2_ALG_OFB, .flags = tpm2_alg_util_flags_mode }, { .name = "cbc", .id = TPM2_ALG_CBC, .flags = tpm2_alg_util_flags_mode }, { .name = "cfb", .id = TPM2_ALG_CFB, .flags = tpm2_alg_util_flags_mode }, { .name = "ecb", .id = TPM2_ALG_ECB, .flags = tpm2_alg_util_flags_mode }, { .name = "symcipher", .id = TPM2_ALG_SYMCIPHER, .flags = tpm2_alg_util_flags_base }, { .name = "keyedhash", .id = TPM2_ALG_KEYEDHASH, .flags = tpm2_alg_util_flags_base }, // Misc { .name = "null", .id = TPM2_ALG_NULL, .flags = tpm2_alg_util_flags_misc | tpm2_alg_util_flags_rsa_scheme }, }; size_t i; for (i = 0; i < ARRAY_LEN(algs); i++) { const alg_pair *alg = &algs[i]; alg_iter_res result = iterator(alg->id, alg->name, alg->flags, userdata); if (result != go) { return; } } } static alg_parser_rc handle_sym_common(const char *ext, TPMT_SYM_DEF_OBJECT *s) { if (ext == NULL || ext[0] == '\0') { ext = "128"; } if (!strncmp(ext, "128", 3)) { s->keyBits.sym = 128; } else if (!strncmp(ext, "192", 3)) { s->keyBits.sym = 192; } else if (!strncmp(ext, "256", 3)) { s->keyBits.sym = 256; } else { return alg_parser_rc_error; } ext += 3; if (*ext == '\0') { ext = "null"; } s->mode.sym = tpm2_alg_util_strtoalg(ext, tpm2_alg_util_flags_mode | tpm2_alg_util_flags_misc); if (s->mode.sym == TPM2_ALG_ERROR) { return alg_parser_rc_error; } return alg_parser_rc_done; } /* * Macro for redundant code collapse in handle_asym_scheme_common * You cannot change all the variables in this, as they are dependent * on names in that routine; this is for simplicity. */ #define do_scheme_halg(scheme, advance, alg) \ do { \ scheme += advance; \ s->scheme.scheme = alg; \ do_scheme_hash_alg = true; \ found = true; \ } while (0) static alg_parser_rc handle_scheme_sign(const char *scheme, TPM2B_PUBLIC *public) { char buf[256]; if (!scheme || scheme[0] == '\0') { scheme = "null"; } int rc = snprintf(buf, sizeof(buf), "%s", scheme); if (rc < 0 || (size_t) rc >= sizeof(buf)) { return alg_parser_rc_error; } // Get the scheme and symetric details TPMS_ASYM_PARMS *s = &public->publicArea.parameters.asymDetail; if (!strcmp(scheme, "null")) { public->publicArea.parameters.asymDetail.scheme.scheme = TPM2_ALG_NULL; return alg_parser_rc_continue; } char *halg = NULL; char *split = strchr(scheme, '-'); if (split) { *split = '\0'; halg = split + 1; } bool found = false; bool do_scheme_hash_alg = false; if (public->publicArea.type == TPM2_ALG_ECC) { if (!strncmp(scheme, "ecdsa", 5)) { do_scheme_halg(scheme, 5, TPM2_ALG_ECDSA); } else if (!strncmp(scheme, "ecdh", 4)) { do_scheme_halg(scheme, 4, TPM2_ALG_ECDH); } else if (!strncmp(scheme, "ecschnorr", 9)) { do_scheme_halg(scheme, 9, TPM2_ALG_ECSCHNORR); } else if (!strncmp(scheme, "ecdaa", 5)) { do_scheme_halg(scheme, 5, TPM2_ALG_ECDAA); /* * ECDAA has both a commit-counter value and hashing algorithm. * The default commit-counter value is set to zero to use the first * commit-id. */ if (scheme[0] == '\0') { scheme = "0"; } TPMS_SIG_SCHEME_ECDAA *e = &s->scheme.details.ecdaa; bool res = tpm2_util_string_to_uint16(scheme, &e->count); if (!res) { return alg_parser_rc_error; } } else if (!strcmp("null", scheme)) { s->scheme.scheme = TPM2_ALG_NULL; } } else { if (!strcmp(scheme, "rsaes")) { /* * rsaes has no hash alg or details, so it MUST * match exactly, notice strcmp and NOT strNcmp! */ s->scheme.scheme = TPM2_ALG_RSAES; found = true; } else if (!strcmp("null", scheme)) { s->scheme.scheme = TPM2_ALG_NULL; found = true; } else if (!strncmp("rsapss", scheme, 6)) { do_scheme_halg(scheme, 6, TPM2_ALG_RSAPSS); } else if (!strncmp("rsassa", scheme, 6)) { do_scheme_halg(scheme, 6, TPM2_ALG_RSASSA); } else if (!strncmp(scheme, "oaep", 4)) { do_scheme_halg(scheme, 4, TPM2_ALG_OAEP); } } /* If we're not expecting a hash alg then halg should be NULL */ if ((!do_scheme_hash_alg && halg) || !found) { return alg_parser_rc_error; } /* if we're expecting a hash alg and none provided default */ if (do_scheme_hash_alg && !halg) { halg = "sha256"; } /* * If the scheme is set, both the encrypt and decrypt attributes cannot be set, * check to see if this is the case, and turn down: * - DECRYPT - If its a signing scheme. * - ENCRYPT - If its an asymmetric enc scheme. */ if (s->scheme.scheme != TPM2_ALG_NULL) { bool is_both_set = !!(public->publicArea.objectAttributes & (TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_DECRYPT)); if (is_both_set) { tpm2_alg_util_flags flags = tpm2_alg_util_algtoflags( s->scheme.scheme); TPMA_OBJECT turn_down_flags = (flags & tpm2_alg_util_flags_sig) ? TPMA_OBJECT_DECRYPT : TPMA_OBJECT_SIGN_ENCRYPT; public->publicArea.objectAttributes &= ~turn_down_flags; } } if (do_scheme_hash_alg) { public->publicArea.parameters.asymDetail.scheme.details.anySig.hashAlg = tpm2_alg_util_strtoalg(halg, tpm2_alg_util_flags_hash); if (public->publicArea.parameters.asymDetail.scheme.details.anySig.hashAlg == TPM2_ALG_ERROR) { return alg_parser_rc_error; } } return alg_parser_rc_continue; } static alg_parser_rc handle_rsa(const char *ext, TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_RSA; TPMS_RSA_PARMS *r = &public->publicArea.parameters.rsaDetail; r->exponent = 0; size_t len = ext ? strlen(ext) : 0; if (len == 0 || ext[0] == '\0') { ext = "2048"; } // Deal with bit size if (!strncmp(ext, "1024", 4)) { r->keyBits = 1024; ext += 4; } else if (!strncmp(ext, "2048", 4)) { r->keyBits = 2048; ext += 4; } else if (!strncmp(ext, "4096", 4)) { r->keyBits = 4096; ext += 4; } else if (!strncmp(ext, "3072", 4)) { r->keyBits = 3072; ext += 4; } else { r->keyBits = 2048; } /* rsa extension should be consumed at this point */ return ext[0] == '\0' ? alg_parser_rc_continue : alg_parser_rc_error; } static alg_parser_rc handle_ecc(const char *ext, TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_ECC; size_t len = ext ? strlen(ext) : 0; if (len == 0 || ext[0] == '\0') { ext = "256"; } TPMS_ECC_PARMS *e = &public->publicArea.parameters.eccDetail; e->kdf.scheme = TPM2_ALG_NULL; if (!strncmp(ext, "192", 3)) { e->curveID = TPM2_ECC_NIST_P192; ext += 3; } else if (!strncmp(ext, "224", 3)) { e->curveID = TPM2_ECC_NIST_P224; ext += 3; } else if (!strncmp(ext, "256", 3)) { e->curveID = TPM2_ECC_NIST_P256; ext += 3; } else if (!strncmp(ext, "384", 3)) { e->curveID = TPM2_ECC_NIST_P384; ext += 3; } else if (!strncmp(ext, "521", 3)) { e->curveID = TPM2_ECC_NIST_P521; ext += 3; } else { e->curveID = TPM2_ECC_NIST_P256; } /* ecc extension should be consumed at this point */ return ext[0] == '\0' ? alg_parser_rc_continue : alg_parser_rc_error; } static alg_parser_rc handle_aes(const char *ext, TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_SYMCIPHER; tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &public->publicArea.objectAttributes); TPMT_SYM_DEF_OBJECT *s = &public->publicArea.parameters.symDetail.sym; s->algorithm = TPM2_ALG_AES; return handle_sym_common(ext, s); } static alg_parser_rc handle_camellia(const char *ext, TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_SYMCIPHER; TPMT_SYM_DEF_OBJECT *s = &public->publicArea.parameters.symDetail.sym; s->algorithm = TPM2_ALG_CAMELLIA; return handle_sym_common(ext, s); } static alg_parser_rc handle_xor(TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_KEYEDHASH; public->publicArea.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_XOR; return alg_parser_rc_continue; } static alg_parser_rc handle_hmac(TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_KEYEDHASH; public->publicArea.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_HMAC; return alg_parser_rc_continue; } static alg_parser_rc handle_keyedhash(TPM2B_PUBLIC *public) { public->publicArea.type = TPM2_ALG_KEYEDHASH; public->publicArea.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_NULL; return alg_parser_rc_done; } static alg_parser_rc handle_object(const char *object, TPM2B_PUBLIC *public) { if (!strncmp(object, "rsa", 3)) { object += 3; return handle_rsa(object, public); } else if (!strncmp(object, "ecc", 3)) { object += 3; return handle_ecc(object, public); } else if (!strncmp(object, "aes", 3)) { object += 3; return handle_aes(object, public); } else if (!strncmp(object, "camellia", 8)) { object += 8; return handle_camellia(object, public); } else if (!strcmp(object, "hmac")) { return handle_hmac(public); } else if (!strcmp(object, "xor")) { return handle_xor(public); } else if (!strcmp(object, "keyedhash")) { return handle_keyedhash(public); } return alg_parser_rc_error; } static alg_parser_rc handle_scheme_keyedhash(const char *scheme, TPM2B_PUBLIC *public) { if (!scheme || scheme[0] == '\0') { scheme = "sha256"; } TPM2_ALG_ID alg = tpm2_alg_util_strtoalg(scheme, tpm2_alg_util_flags_hash); if (alg == TPM2_ALG_ERROR) { return alg_parser_rc_error; } switch (public->publicArea.parameters.keyedHashDetail.scheme.scheme) { case TPM2_ALG_HMAC: public->publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = alg; break; case TPM2_ALG_XOR: public->publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.kdf = TPM2_ALG_KDF1_SP800_108; public->publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.hashAlg = alg; break; default: return alg_parser_rc_error; } return alg_parser_rc_done; } static alg_parser_rc handle_scheme(const char *scheme, TPM2B_PUBLIC *public) { switch (public->publicArea.type) { case TPM2_ALG_RSA: case TPM2_ALG_ECC: return handle_scheme_sign(scheme, public); case TPM2_ALG_KEYEDHASH: return handle_scheme_keyedhash(scheme, public); default: return alg_parser_rc_error; } return alg_parser_rc_error; } static alg_parser_rc handle_asym_detail(const char *detail, TPM2B_PUBLIC *public) { bool is_restricted = !!(public->publicArea.objectAttributes & TPMA_OBJECT_RESTRICTED); bool is_rsapps = public->publicArea.parameters.asymDetail.scheme.scheme == TPM2_ALG_RSAPSS; switch (public->publicArea.type) { case TPM2_ALG_RSA: case TPM2_ALG_ECC: if (!detail || detail[0] == '\0') { detail = is_restricted || is_rsapps ? "aes128cfb" : "null"; } TPMT_SYM_DEF_OBJECT *s = &public->publicArea.parameters.symDetail.sym; if (!strncmp(detail, "aes", 3)) { s->algorithm = TPM2_ALG_AES; return handle_sym_common(detail + 3, s); } else if (!strncmp(detail, "camellia", 8)) { s->algorithm = TPM2_ALG_CAMELLIA; return handle_sym_common(detail + 8, s); } else if (!strcmp(detail, "null")) { s->algorithm = TPM2_ALG_NULL; return alg_parser_rc_done; } /* no default */ } return alg_parser_rc_error; } bool tpm2_alg_util_handle_ext_alg(const char *alg_spec, TPM2B_PUBLIC *public) { char buf[256]; if (!alg_spec) { return false; } int rc = snprintf(buf, sizeof(buf), "%s", alg_spec); if (rc < 0 || (size_t) rc >= sizeof(buf)) { goto error; } char *object = NULL; char *scheme = NULL; char *symdetail = NULL; char *b = buf; char *tok = NULL; char *saveptr = NULL; unsigned i = 0; while ((tok = strtok_r(b, ":", &saveptr))) { b = NULL; switch (i) { case 0: object = tok; break; case 1: scheme = tok; break; case 2: symdetail = tok; break; default: goto error; } i++; } if (i == 0) { goto error; } alg_parser_rc prc = handle_object(object, public); if (prc == alg_parser_rc_done) { /* we must have exhausted all the entries or it's an error */ return scheme || symdetail ? false : true; } if (prc == alg_parser_rc_error) { return false; } /* * at this point we either have scheme or asym detail, if it * doesn't process as a scheme shuffle it to asym detail */ for (i = 0; i < 2; i++) { prc = handle_scheme(scheme, public); if (prc == alg_parser_rc_done) { /* we must have exhausted all the entries or it's an error */ return symdetail ? false : true; } if (prc == alg_parser_rc_error) { /* * if symdetail is set scheme must be consumed * unless scheme has been skipped by setting it * to NULL */ if (symdetail && scheme) { return false; } symdetail = scheme; scheme = NULL; continue; } /* success in processing scheme */ break; } /* handle asym detail */ prc = handle_asym_detail(symdetail, public); if (prc != alg_parser_rc_done) { goto error; } return true; error: LOG_ERR("Could not handle algorithm spec: \"%s\"", alg_spec); return false; } tool_rc tpm2_alg_util_handle_rsa_ext_alg(const char *alg_spec, TPM2B_PUBLIC *public) { #define RSA_KEYBITS_STRLEN 6 char *ext_alg_str = calloc(1, strlen(alg_spec) + strlen("rsa") + RSA_KEYBITS_STRLEN); strcat(ext_alg_str, "rsa"); switch(public->publicArea.parameters.rsaDetail.keyBits) { case 1024: strcat(ext_alg_str, "1024:"); break; case 2048: strcat(ext_alg_str, "2048:"); break; case 3072: strcat(ext_alg_str, "3072:"); break; case 4096: strcat(ext_alg_str, "4096:"); break; }; strcat(ext_alg_str, alg_spec); bool result = tpm2_alg_util_handle_ext_alg(ext_alg_str, public); free(ext_alg_str); return result ? tool_rc_success : tool_rc_general_error; } static alg_iter_res find_match(TPM2_ALG_ID id, const char *name, tpm2_alg_util_flags flags, void *userdata) { alg_pair *search_data = (alg_pair *) userdata; /* * if name, then search on name, else * search by id. */ if (search_data->name && !strcmp(search_data->name, name)) { alg_iter_res res = search_data->flags & flags ? found : stop; if (res == found) { search_data->id = id; search_data->_flags = flags; } return res; } else if (search_data->id == id) { alg_iter_res res = search_data->flags & flags ? found : stop; if (res == found) { search_data->name = name; search_data->_flags = flags; } return res; } return go; } TPM2_ALG_ID tpm2_alg_util_strtoalg(const char *name, tpm2_alg_util_flags flags) { alg_pair userdata = { .name = name, .id = TPM2_ALG_ERROR, .flags = flags }; if (name) { tpm2_alg_util_for_each_alg(find_match, &userdata); } return userdata.id; } const char *tpm2_alg_util_algtostr(TPM2_ALG_ID id, tpm2_alg_util_flags flags) { alg_pair userdata = { .name = NULL, .id = id, .flags = flags }; tpm2_alg_util_for_each_alg(find_match, &userdata); return userdata.name; } tpm2_alg_util_flags tpm2_alg_util_algtoflags(TPM2_ALG_ID id) { alg_pair userdata = { .name = NULL, .id = id, .flags = tpm2_alg_util_flags_any, ._flags = tpm2_alg_util_flags_none }; tpm2_alg_util_for_each_alg(find_match, &userdata); return userdata._flags; } TPM2_ALG_ID tpm2_alg_util_from_optarg(const char *optarg, tpm2_alg_util_flags flags) { TPM2_ALG_ID halg; bool res = tpm2_util_string_to_uint16(optarg, &halg); if (!res) { halg = tpm2_alg_util_strtoalg(optarg, flags); } else { if (!tpm2_alg_util_algtostr(halg, flags)) { return TPM2_ALG_ERROR; } } return halg; } UINT16 tpm2_alg_util_get_hash_size(TPMI_ALG_HASH id) { switch (id) { case TPM2_ALG_SHA1: return TPM2_SHA1_DIGEST_SIZE; case TPM2_ALG_SHA256: return TPM2_SHA256_DIGEST_SIZE; case TPM2_ALG_SHA384: return TPM2_SHA384_DIGEST_SIZE; case TPM2_ALG_SHA512: return TPM2_SHA512_DIGEST_SIZE; case TPM2_ALG_SM3_256: return TPM2_SM3_256_DIGEST_SIZE; /* no default */ } return 0; } static const char *hex_to_byte_err(int rc) { switch (rc) { case -2: return "String not even in length"; case -3: return "Non hex digit found"; case -4: return "Hex value too big for digest"; } return "unknown"; } bool pcr_parse_digest_list(char **argv, int len, tpm2_pcr_digest_spec *digest_spec) { /* * int is chosen because of what is passed in from main, avoids * sign differences. * */ int i; for (i = 0; i < len; i++) { tpm2_pcr_digest_spec *dspec = &digest_spec[i]; UINT32 count = 0; /* * Split :=,... on : and separate with null byte, ie: * '\0' '\0' * * Start by splitting out the pcr index, and validating it. */ char *spec_str = argv[i]; char *pcr_index_str = spec_str; char *digest_spec_str = strchr(spec_str, ':'); if (!digest_spec_str) { LOG_ERR("Expecting : in digest spec, not found, got: \"%s\"", spec_str); return false; } *digest_spec_str = '\0'; digest_spec_str++; bool result = pcr_get_id(pcr_index_str, &dspec->pcr_index); if (!result) { LOG_ERR("Got invalid PCR Index: \"%s\", in digest spec: \"%s\"", pcr_index_str, spec_str); return false; } /* now that the pcr_index is removed, parse the remaining =,.. */ char *digest_hash_tok; char *save_ptr = NULL; /* keep track of digests we have seen */ while ((digest_hash_tok = strtok_r(digest_spec_str, ",", &save_ptr))) { digest_spec_str = NULL; if (count >= ARRAY_LEN(dspec->digests.digests)) { LOG_ERR("Specified too many digests per spec, max is: %zu", ARRAY_LEN(dspec->digests.digests)); return false; } TPMT_HA *d = &dspec->digests.digests[count]; char *stralg = digest_hash_tok; char *split = strchr(digest_hash_tok, '='); if (!split) { LOG_ERR("Expecting = in = spec, got: " "\"%s\"", digest_hash_tok); return false; } *split = '\0'; split++; char *data = split; /* * Convert and validate the hash algorithm. It should be a hash algorithm */ TPM2_ALG_ID alg = tpm2_alg_util_from_optarg(stralg, tpm2_alg_util_flags_hash); if (alg == TPM2_ALG_ERROR) { LOG_ERR("Could not convert algorithm, got: \"%s\"", stralg); return false; } d->hashAlg = alg; /* fill up the TPMT_HA structure with algorithm and digest */ BYTE *digest_data = (BYTE *) &d->digest; UINT16 expected_hash_size = tpm2_alg_util_get_hash_size(alg); /* strip any preceding hex on the data as tpm2_util_hex_to_byte_structure doesn't support it */ bool is_hex = !strncmp("0x", data, 2); if (is_hex) { data += 2; } UINT16 size = expected_hash_size; int rc = tpm2_util_hex_to_byte_structure(data, &size, digest_data); if (rc) { LOG_ERR("Error \"%s\" converting hex string as data, got:" " \"%s\"", hex_to_byte_err(rc), data); return false; } if (expected_hash_size != size) { LOG_ERR("Algorithm \"%s\" expects a size of %u bytes, got: %u", stralg, expected_hash_size, size); return false; } count++; } if (!count) { LOG_ERR("Missing or invalid = spec for pcr:" " \"%s\"", pcr_index_str); return false; } /* assign count at the end, so count is 0 on error */ dspec->digests.count = count; } return true; } static tool_rc tpm2_public_to_scheme(ESYS_CONTEXT *ectx, ESYS_TR key, TPMI_ALG_PUBLIC *type, TPMT_SIG_SCHEME *sigscheme) { tool_rc rc = tool_rc_general_error; TPM2B_PUBLIC *out_public = NULL; rc = tpm2_readpublic(ectx, key, &out_public, NULL, NULL); if (rc != tool_rc_success) { return rc; } *type = out_public->publicArea.type; TPMU_PUBLIC_PARMS *pp = &out_public->publicArea.parameters; /* * Symmetric ciphers do not have signature algorithms */ if (*type == TPM2_ALG_SYMCIPHER) { LOG_ERR("Cannot convert symmetric cipher to signature algorithm"); goto out; } /* * Now we are looking at specific algorithms that the keys * are bound to, so we need to populate that in the scheme */ if ((*type == TPM2_ALG_RSA || *type == TPM2_ALG_ECC)) { sigscheme->scheme = pp->asymDetail.scheme.scheme; /* they all have a hash alg, and for most schemes' thats it */ sigscheme->details.any.hashAlg = pp->asymDetail.scheme.details.anySig.hashAlg; rc = tool_rc_success; goto out; } /* keyed hash could be the only one left */ sigscheme->scheme = pp->keyedHashDetail.scheme.scheme; sigscheme->details.hmac.hashAlg = pp->keyedHashDetail.scheme.details.hmac.hashAlg; rc = tool_rc_success; out: Esys_Free(out_public); return rc; } static bool is_null_alg(TPM2_ALG_ID alg) { return !alg || alg == TPM2_ALG_NULL; } tool_rc tpm2_alg_util_get_signature_scheme(ESYS_CONTEXT *ectx, ESYS_TR key_handle, TPMI_ALG_HASH *halg, TPMI_ALG_SIG_SCHEME sig_scheme, TPMT_SIG_SCHEME *scheme) { TPMI_ALG_PUBLIC type = TPM2_ALG_NULL; TPMT_SIG_SCHEME object_sigscheme = { 0 }; tool_rc rc = tpm2_public_to_scheme(ectx, key_handle, &type, &object_sigscheme); if (rc != tool_rc_success) { return rc; } LOG_INFO("hashing alg in: 0x%x", *halg); LOG_INFO("sig scheme in: 0x%x", sig_scheme); /* * if scheme is requested by the user, verify the scheme will work */ if (!is_null_alg(sig_scheme) && !is_null_alg(object_sigscheme.scheme) && object_sigscheme.scheme != sig_scheme) { LOG_ERR("Requested sign scheme \"%s\" but object only supports sign scheme \%s\")", tpm2_alg_util_algtostr(sig_scheme, tpm2_alg_util_flags_any), tpm2_alg_util_algtostr(object_sigscheme.scheme, tpm2_alg_util_flags_any)); return tool_rc_general_error; } else { /* * set a default for RSA, ECC or KEYEDHASH * Not ECDAA, it wasn't chosen because it needs count as well, * so any.hashAlg doesn't work. Aksim what would you pick for count? * See bug #2071 to figure out what to do if an ECDAA scheme comes back. * * Assign scheme based on type: * TPM2_ALG_RSA --> TPM2_ALG_RSSASSA * TPM2_ALG_ECC --> TPM2_ALG_ECDSA * TPM2_ALG_KEYEDHASH --> TPM2_ALG_HMAC */ if (is_null_alg(sig_scheme)) { object_sigscheme.scheme = (type == TPM2_ALG_RSA) ? TPM2_ALG_RSASSA : (type == TPM2_ALG_ECC) ? TPM2_ALG_ECDSA : TPM2_ALG_HMAC; } else { object_sigscheme.scheme = sig_scheme; } } /* if hash alg is requested by the user, verify the hash alg will work */ if (!is_null_alg(*halg) && !is_null_alg(object_sigscheme.details.any.hashAlg) && object_sigscheme.details.any.hashAlg != *halg) { LOG_ERR("Requested signature hash alg \"%s\" but object only supports signature hash alg \%s\")", tpm2_alg_util_algtostr(*halg, tpm2_alg_util_flags_any), tpm2_alg_util_algtostr(object_sigscheme.details.any.hashAlg, tpm2_alg_util_flags_any)); return tool_rc_general_error; } else { object_sigscheme.details.any.hashAlg = is_null_alg(*halg) ? TPM2_ALG_SHA256 : *halg; } /* everything requested matches, or we got defaults move along */ *halg = object_sigscheme.details.any.hashAlg; *scheme = object_sigscheme; LOG_INFO("halg out: 0x%x", *halg); LOG_INFO("sig scheme out: 0x%x", scheme->scheme); return tool_rc_success; } tool_rc tpm2_alg_util_public_init(char *alg_details, char *name_halg, char *attrs, char *auth_policy, TPMA_OBJECT def_attrs, TPM2B_PUBLIC *public) { memset(public, 0, sizeof(*public)); /* load a policy from a path if present */ if (auth_policy) { public->publicArea.authPolicy.size = sizeof(public->publicArea.authPolicy.buffer); bool res = files_load_bytes_from_path(auth_policy, public->publicArea.authPolicy.buffer, &public->publicArea.authPolicy.size); if (!res) { return tool_rc_general_error; } } /* Set the hashing algorithm used for object name */ public->publicArea.nameAlg = name_halg ? tpm2_alg_util_from_optarg(name_halg, tpm2_alg_util_flags_hash) : TPM2_ALG_SHA256; if (public->publicArea.nameAlg == TPM2_ALG_ERROR) { LOG_ERR("Invalid name hashing algorithm, got\"%s\"", name_halg); return tool_rc_unsupported; } /* Set specified attributes or use default */ if (attrs) { bool res = tpm2_attr_util_obj_from_optarg(attrs, &public->publicArea.objectAttributes); if (!res) { return tool_rc_unsupported; } } else { public->publicArea.objectAttributes = def_attrs; } /* * Some defaults may not be OK with the specified algorithms, if their defaults, * tweak the Object Attributes, if specified by user, complain things will not * work together and suggest attributes. This allows the user to verify what the * want. */ TPM2B_PUBLIC tmp = *public; bool res = tpm2_alg_util_handle_ext_alg(alg_details, &tmp); if (!res) { LOG_ERR("Could not handle algorithm: \"%s\"", alg_details); return tool_rc_unsupported; } if (attrs && tmp.publicArea.objectAttributes != public->publicArea.objectAttributes) { char *proposed_attrs = tpm2_attr_util_obj_attrtostr( tmp.publicArea.objectAttributes); LOG_ERR("Specified attributes \"%s\" and algorithm specifier \"%s\" do " "not work together, try attributes: \"%s\"", attrs, alg_details, proposed_attrs); free(proposed_attrs); return tool_rc_unsupported; } *public = tmp; return tool_rc_success; } const char *tpm2_alg_util_ecc_to_str(TPM2_ECC_CURVE curve_id) { switch (curve_id) { case TPM2_ECC_NIST_P192: return "NIST p192"; case TPM2_ECC_NIST_P224: return "NIST p224"; case TPM2_ECC_NIST_P256: return "NIST p256"; case TPM2_ECC_NIST_P384: return "NIST p384"; case TPM2_ECC_NIST_P521: return "NIST 521"; case TPM2_ECC_BN_P256: return "BN P256"; case TPM2_ECC_BN_P638: return "BN P638"; case TPM2_ECC_SM2_P256: return "SM2 p256"; /* no default */ } return NULL; } bool tpm2_alg_util_is_aes_size_valid(UINT16 size_in_bytes) { switch (size_in_bytes) { case 16: case 24: case 32: return true; default: LOG_ERR("Invalid AES key size, got %u bytes, expected 16,24 or 32", size_in_bytes); return false; } } tpm2-tools-5.2/lib/tpm2_alg_util.h000066400000000000000000000143301412464516500170720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_ALG_UTIL_H_ #define LIB_TPM2_ALG_UTIL_H_ #include #include #include "tool_rc.h" typedef enum tpm2_alg_util_flags tpm2_alg_util_flags; enum tpm2_alg_util_flags { tpm2_alg_util_flags_none = 0, tpm2_alg_util_flags_hash = 1 << 0, tpm2_alg_util_flags_keyedhash = 1 << 1, tpm2_alg_util_flags_symmetric = 1 << 2, tpm2_alg_util_flags_asymmetric = 1 << 3, tpm2_alg_util_flags_kdf = 1 << 4, tpm2_alg_util_flags_mgf = 1 << 5, tpm2_alg_util_flags_sig = 1 << 6, tpm2_alg_util_flags_mode = 1 << 7, tpm2_alg_util_flags_base = 1 << 8, tpm2_alg_util_flags_misc = 1 << 9, tpm2_alg_util_flags_enc_scheme = 1 << 10, tpm2_alg_util_flags_rsa_scheme = 1 << 11, tpm2_alg_util_flags_any = ~0 }; /** * Convert a "nice-name" string to an algorithm id. * @param name * The "nice-name" to convert. * @return * TPM2_ALG_ERROR on error, or a valid algorithm identifier. */ TPM2_ALG_ID tpm2_alg_util_strtoalg(const char *name, tpm2_alg_util_flags flags); /** * Convert an id to a nice-name. * @param id * The id to convert. * @return * The nice-name. */ const char *tpm2_alg_util_algtostr(TPM2_ALG_ID id, tpm2_alg_util_flags flags); /** * XXX DOC AND TESTME * @param id * @return */ tpm2_alg_util_flags tpm2_alg_util_algtoflags(TPM2_ALG_ID id); /** * Converts either a string from algorithm number or algorithm nice-name to * an algorithm id. * @param optarg * The string to convert from an algorithm number or nice name. * @return * TPM2_ALG_ERROR on error or the algorithm id. */ TPM2_ALG_ID tpm2_alg_util_from_optarg(const char *optarg, tpm2_alg_util_flags flags); /** * Contains the information from parsing an argv style vector of strings for * pcr digest language specifications. */ typedef struct tpm2_pcr_digest_spec tpm2_pcr_digest_spec; struct tpm2_pcr_digest_spec { TPML_DIGEST_VALUES digests; TPMI_DH_PCR pcr_index; }; /** * Parses an argv array that contains a digest specification at each location * within argv. * * The digest specification is as follows: * - A pcr identifier as understood by strtoul with 0 as the base. * - A colon followed by the algorithm hash specification. * - The algorithm hash specification is as follows: * - The algorithm friendly name or raw numerical as understood by * strtoul with a base of 0. * - An equals sign * - The hex hash value, * * This all distills to a string that looks like this: * := * * Example: * "4:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" * * Note: * Multiple specifications of PCR and hash are OK. Multiple hashes * cause the pcr to be extended with both hashes. Multiple same PCR * values cause the PCR to be extended multiple times. Extension * is done in order from left to right as specified. * * At most 5 hash extensions per PCR entry are supported. This * is to keep the parser simple. * * @param argv * The argv of digest specifications to parse. * @param len * The number of digest specifications to parse. * @param digests * An array of tpm2_pcr_digest_spec big enough to hold len items. * @return * True if parsing was successful, False otherwise. * @note * This function logs errors via LOG_ERR. */ bool pcr_parse_digest_list(char **argv, int len, tpm2_pcr_digest_spec *digest_spec); /** * Retrieves the size of a hash in bytes for a given hash * algorithm or 0 if unknown/not found. * @param id * The HASH algorithm identifier. * @return * 0 on failure or the size of the hash bytes. */ UINT16 tpm2_alg_util_get_hash_size(TPMI_ALG_HASH id); /** * Retrieves an appropriate signature scheme (scheme) signable by * specified key (keyHandle) and hash algorithm (halg). * @param context * Enhanced System API (ESAPI) context for tpm * @param keyHandle * Handle to key used in signing operation * @param halg * The requested hash algorithm for message, the contents are checked * against what the object will support. If TPM2_ALG_NULL is specified, then the * hash algorithm is updated to what the object will support. * @param sig_scheme * Signature scheme (optional, use TPM2_ALG_NULL for default) * @param scheme * Signature scheme output * @param default_hash_sha1 * Set to true to make the default hash sha1 over sha256 * @return * tool_rc indicating status. * On error scheme is left unmodified. */ tool_rc tpm2_alg_util_get_signature_scheme(ESYS_CONTEXT *context, ESYS_TR key_handle, TPMI_ALG_HASH *halg, TPMI_ALG_SIG_SCHEME sig_scheme, TPMT_SIG_SCHEME *scheme); /** * * @param alg_spec * Friendly specification of public algorithm set (algname:...:....) * @param public * Public structure which will contain relevant information about * specified algorithm * @pre public is caller allocated and must not be NULL * @return */ bool tpm2_alg_util_handle_ext_alg(const char *alg_spec, TPM2B_PUBLIC *public); /** * Retrieves the scheme information for an RSA key to be used in * TPM2_CC_RSA_Encrypt or TPM2_CC_RSA_Decrypt * @param alg_spec * Friendly specification of the RSA scheme (oaep-sha1) * @param public * Public structure which will contain relevant information about * specified algorithm */ tool_rc tpm2_alg_util_handle_rsa_ext_alg(const char *alg_spec, TPM2B_PUBLIC *public); /** * * @param alg_details * @param name_halg * @param attrs * @param auth_policy * @param def_attrs * @param is_sealing * @param public * @return */ tool_rc tpm2_alg_util_public_init(char *alg_details, char *name_halg, char *attrs, char *auth_policy, TPMA_OBJECT def_attrs, TPM2B_PUBLIC *public); /** * Returns an ECC curve as a friendly name. * @param curve_id * The curve to look up a friendly string for. * @return * The friendly string or NULL if not found. */ const char *tpm2_alg_util_ecc_to_str(TPM2_ECC_CURVE curve_id); /** * Determines if a size is a valid AES key size. * @param size_in_bytes * The size of a potential AES key in bytes. * @return * true if valid, false otherwise. */ bool tpm2_alg_util_is_aes_size_valid(UINT16 size_in_bytes); #endif /* LIB_TPM2_ALG_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_attr_util.c000066400000000000000000000410211412464516500172710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "log.h" #include "tpm2_attr_util.h" #define dispatch_no_arg_add(x) \ { .name = str(x), .callback=(action)x, .width = 1 } #define dispatch_arg_add(x, w) \ { .name = str(x), .callback=(action)x, .width = w } #define dispatch_reserved(pos) \ { .name = "", .callback=NULL, .width = 1 } typedef enum dispatch_error dispatch_error; enum dispatch_error { dispatch_ok = 0, dispatch_err, dispatch_no_match, }; typedef bool (*action)(void *obj, char *arg); typedef struct dispatch_table dispatch_table; struct dispatch_table { char *name; action callback; unsigned width; /* the width of the field, CANNOT be 0 */ }; static bool authread(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_AUTHREAD; return true; } static bool authwrite(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_AUTHWRITE; return true; } static bool clear_stclear(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_CLEAR_STCLEAR; return true; } static bool globallock(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_GLOBALLOCK; return true; } static bool no_da(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_NO_DA; return true; } static bool orderly(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_ORDERLY; return true; } static bool ownerread(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_OWNERREAD; return true; } static bool ownerwrite(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_OWNERWRITE; return true; } static bool platformcreate(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_PLATFORMCREATE; return true; } static bool policyread(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_POLICYREAD; return true; } static bool policywrite(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_POLICYWRITE; return true; } static bool policydelete(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_POLICY_DELETE; return true; } static bool ppread(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_PPREAD; return true; } static bool ppwrite(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_PPWRITE; return true; } static bool readlocked(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_READLOCKED; return true; } static bool read_stclear(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_READ_STCLEAR; return true; } static bool writeall(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_WRITEALL; return true; } static bool writedefine(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_WRITEDEFINE; return true; } static bool writelocked(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_WRITELOCKED; return true; } static bool write_stclear(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_WRITE_STCLEAR; return true; } static bool written(TPMA_NV *nv, char *arg) { UNUSED(arg); *nv |= TPMA_NV_WRITTEN; return true; } static bool lookup_nt_friendly_name(const char *arg, uint16_t *type) { if (!strcmp(arg, "ordinary")) { // Nothing to do } else if (!strcmp(arg, "counter")) { *type = TPM2_NT_COUNTER; } else if (!strcmp(arg, "bits")) { *type = TPM2_NT_BITS; } else if (!strcmp(arg, "extend")) { *type = TPM2_NT_EXTEND; } else if (!strcmp(arg, "pinfail")) { *type = TPM2_NT_PIN_FAIL; } else if (!strcmp(arg, "pinpass")) { *type = TPM2_NT_PIN_PASS; } else { LOG_ERR("Unknown NT type specifier, got: \"%s\"", arg); return false; } return true; } static bool nt(TPMA_NV *nv, char *arg) { uint16_t value; bool result = tpm2_util_string_to_uint16(arg, &value); if (!result) { result = lookup_nt_friendly_name(arg, &value); if (!result) { LOG_ERR("Could not convert NT field, got \"%s\"." "Expected a number or friendly name", arg); return false; } } /* nt space is 4 bits, so max of 15 */ if (value > 0x0F) { LOG_ERR("Field TPM_NT of type TPMA_NV is only 4 bits," "value \"%s\" to big!", arg); return false; } *nv &= ~TPMA_NV_TPM2_NT_MASK; *nv |= value << 4; return true; } /* * The order of this table must be in order with the bit defines in table 204: * https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf * * This table is in bitfield order, thus the index of a bit set in a TPMA_NV * can be used to lookup the name. * * if not the logic in tpm2_nv_util_strtoattr would need to change! */ static dispatch_table nv_attr_table[] = { // Bit Index dispatch_no_arg_add(ppwrite), // 0 dispatch_no_arg_add(ownerwrite), // 1 dispatch_no_arg_add(authwrite), // 2 dispatch_no_arg_add(policywrite), // 3 dispatch_arg_add(nt, 4), // 4 dispatch_arg_add(nt, 3), // 5 dispatch_arg_add(nt, 2), // 6 dispatch_arg_add(nt, 1), // 7 dispatch_reserved(8), // 8 dispatch_reserved(9), // 9 dispatch_no_arg_add(policydelete), // 10 dispatch_no_arg_add(writelocked), // 11 dispatch_no_arg_add(writeall), // 12 dispatch_no_arg_add(writedefine), // 13 dispatch_no_arg_add(write_stclear), // 14 dispatch_no_arg_add(globallock), // 15 dispatch_no_arg_add(ppread), // 16 dispatch_no_arg_add(ownerread), // 17 dispatch_no_arg_add(authread), // 18 dispatch_no_arg_add(policyread), // 19 dispatch_reserved(20), // 20 dispatch_reserved(21), // 21 dispatch_reserved(22), // 22 dispatch_reserved(23), // 23 dispatch_reserved(24), // 24 dispatch_no_arg_add(no_da), // 25 dispatch_no_arg_add(orderly), // 26 dispatch_no_arg_add(clear_stclear), // 27 dispatch_no_arg_add(readlocked), // 28 dispatch_no_arg_add(written), // 29 dispatch_no_arg_add(platformcreate), // 30 dispatch_no_arg_add(read_stclear), // 31 }; static bool fixedtpm(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_FIXEDTPM; return true; } static bool stclear(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_STCLEAR; return true; } static bool fixedparent(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_FIXEDPARENT; return true; } static bool sensitivedataorigin(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_SENSITIVEDATAORIGIN; return true; } static bool userwithauth(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_USERWITHAUTH; return true; } static bool adminwithpolicy(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_ADMINWITHPOLICY; return true; } static bool noda(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_NODA; return true; } static bool encryptedduplication(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_ENCRYPTEDDUPLICATION; return true; } static bool restricted(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_RESTRICTED; return true; } static bool decrypt(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_DECRYPT; return true; } static bool sign(TPMA_OBJECT *obj, char *arg) { UNUSED(arg); *obj |= TPMA_OBJECT_SIGN_ENCRYPT; return true; } static dispatch_table obj_attr_table[] = { // Bit Index dispatch_reserved(0), // 0 dispatch_no_arg_add(fixedtpm), // 1 dispatch_no_arg_add(stclear), // 2 dispatch_reserved(3), // 3 dispatch_no_arg_add(fixedparent), // 4 dispatch_no_arg_add(sensitivedataorigin), // 5 dispatch_no_arg_add(userwithauth), // 6 dispatch_no_arg_add(adminwithpolicy), // 7 dispatch_reserved(8), // 8 dispatch_reserved(9), // 9 dispatch_no_arg_add(noda), // 10 dispatch_no_arg_add(encryptedduplication), // 11 dispatch_reserved(12), // 12 dispatch_reserved(13), // 13 dispatch_reserved(14), // 14 dispatch_reserved(15), // 15 dispatch_no_arg_add(restricted), // 16 dispatch_no_arg_add(decrypt), // 17 dispatch_no_arg_add(sign), // 18 dispatch_reserved(19), // 19 dispatch_reserved(20), // 20 dispatch_reserved(21), // 21 dispatch_reserved(22), // 22 dispatch_reserved(23), // 23 dispatch_reserved(24), // 24 dispatch_reserved(25), // 25 dispatch_reserved(26), // 26 dispatch_reserved(27), // 27 dispatch_reserved(28), // 28 dispatch_reserved(29), // 29 dispatch_reserved(30), // 30 dispatch_reserved(31), // 31 }; static bool token_match(const char *name, const char *token, bool has_arg, char **sep) { /* if it has an argument, we expect a separator */ size_t match_len = strlen(token); if (has_arg) { *sep = strchr(token, '='); if (*sep) { match_len = *sep - token; } } return !strncmp(name, token, match_len); } static dispatch_error handle_dispatch(dispatch_table *d, char *token, TPMA_NV *nvattrs) { char *name = d->name; action cb = d->callback; bool has_arg = d->width > 1; /* if no callback, then its a reserved block, just skip it */ if (!cb) { return dispatch_no_match; } char *sep = NULL; bool match = token_match(name, token, has_arg, &sep); if (!match) { return dispatch_no_match; } /* * If it has an argument, match should have found the separator. */ char *arg = NULL; if (has_arg) { if (!sep) { LOG_ERR("Expected argument for \"%s\", got none.", token); return dispatch_err; } /* split token on = */ *sep = '\0'; sep++; if (!*sep) { LOG_ERR("Expected argument for \"%s\", got none.", token); return dispatch_err; } /* valid argument string, assign */ arg = sep; } bool result = cb(nvattrs, arg); return result ? dispatch_ok : dispatch_err; } static bool common_strtoattr(char *attribute_list, void *attrs, dispatch_table *table, size_t size) { char *token; char *save; /* * This check is solely to prevent GCC from complaining on: * error: ‘attribute_list’ may be used uninitialized in this function [-Werror=maybe-uninitialized] * Might as well check nvattrs as well. */ if (!attribute_list || !attrs) { LOG_ERR("attribute list or attributes structure is NULL"); return false; } while ((token = strtok_r(attribute_list, "|", &save))) { attribute_list = NULL; bool did_dispatch = false; size_t i; for (i = 0; i < size; i++) { dispatch_table *d = &table[i]; dispatch_error err = handle_dispatch(d, token, attrs); if (err == dispatch_ok) { did_dispatch = true; break; } else if (err == dispatch_err) { return false; } /* dispatch_no_match --> keep looking */ } /* did we dispatch?, If not log error and return */ if (!did_dispatch) { char *tmp = strchr(token, '='); if (tmp) { *tmp = '\0'; } LOG_ERR("Unknown token: \"%s\" found.", token); return false; } } return true; } bool tpm2_attr_util_nv_strtoattr(char *attribute_list, TPMA_NV *nvattrs) { memset(nvattrs, 0, sizeof(*nvattrs)); return common_strtoattr(attribute_list, nvattrs, nv_attr_table, ARRAY_LEN(nv_attr_table)); } bool tpm2_attr_util_obj_strtoattr(char *attribute_list, TPMA_OBJECT *objattrs) { memset(objattrs, 0, sizeof(*objattrs)); return common_strtoattr(attribute_list, objattrs, obj_attr_table, ARRAY_LEN(obj_attr_table)); } static UINT8 find_first_set(UINT32 bits) { UINT8 n = 0; if (!bits) { return n; } if (!(bits & 0x0000FFFF)) { n += 16; bits >>= 16; } if (!(bits & 0x000000FF)) { n += 8; bits >>= 8; } if (!(bits & 0x0000000F)) { n += 4; bits >>= 4; } if (!(bits & 0x00000003)) { n += 2; bits >>= 2; } if (!(bits & 0x00000001)) n += 1; return n; } static char *tpm2_attr_util_common_attrtostr(UINT32 attrs, dispatch_table *table, size_t size) { if (attrs == 0) { return strdup(""); } /* * Get how many bits are set in the attributes and then find the longest * "name". * * pop_cnt * max_name_len + pop_cnt - 1 (for the | separators) + 4 * (for nv field equals in hex) + 1 for null byte. * * This will provide us an ample buffer size for generating the string * in without having to constantly realloc. */ UINT32 pop_cnt = tpm2_util_pop_count(attrs); size_t i; size_t max_name_len = 0; for (i = 0; i < size; i++) { dispatch_table *d = &table[i]; size_t name_len = strlen(d->name); max_name_len = name_len > max_name_len ? name_len : max_name_len; } size_t length = pop_cnt * max_name_len + pop_cnt - 1 + 3; char *str = calloc(length, 1); if (!str) { return NULL; } size_t string_index = 0; /* * Start at the lowest, first bit set, index into the array, * grab the data needed, and move on. */ while (attrs) { UINT8 bit_index = find_first_set(attrs); dispatch_table *d = &table[bit_index]; const char *name = d->name; unsigned w = d->width; /* current position and size left of the string */ char *s = &str[string_index]; size_t left = length - string_index; /* this is a mask that is field width wide */ UINT8 mask = ((UINT32) 1 << w) - 1; /* get the value in the field before clearing attrs out */ UINT8 field_values = (attrs & mask << bit_index) >> bit_index; /* * turn off the parsed bit(s) index, using width to turn off everything in a * field */ attrs &= ~(mask << bit_index); int n; /* * if the callback is NULL, we are either in a field middle or reserved * section which is weird, just add the name in. In the case of being * in the middle of the field, we will add a bunch of errors to the string, * but it would be better to attempt to show all the data in string form, * rather than bail. * * Fields are either 1 or > 1. */ if (w == 1) { n = snprintf(s, left, attrs ? "%s|" : "%s", name); } else { /* deal with the field */ n = snprintf(s, left, attrs ? "%s=0x%X|" : "%s=0x%X", name, field_values); } /* check if there was enough space left in s */ if ((n < 0) || ((unsigned) n >= left)) { break; } string_index += n; } return str; } char *tpm2_attr_util_nv_attrtostr(TPMA_NV nvattrs) { return tpm2_attr_util_common_attrtostr(nvattrs, nv_attr_table, ARRAY_LEN(nv_attr_table)); } char *tpm2_attr_util_obj_attrtostr(TPMA_OBJECT objattrs) { return tpm2_attr_util_common_attrtostr(objattrs, obj_attr_table, ARRAY_LEN(obj_attr_table)); } bool tpm2_attr_util_obj_from_optarg(char *argvalue, TPMA_OBJECT *objattrs) { bool res = tpm2_util_string_to_uint32(argvalue, objattrs); if (!res) { res = tpm2_attr_util_obj_strtoattr(argvalue, objattrs); } return res; } tpm2-tools-5.2/lib/tpm2_attr_util.h000066400000000000000000000051741412464516500173070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_ATTR_UTIL_H_ #define LIB_TPM2_ATTR_UTIL_H_ #include #include /** * Converts a list of | (pipe) separated attributes as defined in tavle 204 * of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf * to an actual bit field representation. The trailing TPMA_NV_ can be omitted and must be lower-case. * For example, TPMA_NV_PPWRITE, becomes ppwrite. To append them together, just do the pipe in between. * ppwrite|ownerwrite. * * @param attribute_list * The attribute string to parse, which may be modified in place. * @param nvattrs * The TPMA_NV attributes set based on the attribute list. Only valid on true returns. * @return * true on success, false on error. */ bool tpm2_attr_util_nv_strtoattr(char *attribute_list, TPMA_NV *nvattrs); /** * Like tpm2_attr_util_nv_strtoattr() but converts TPMA_OBJECT attributes as defined in: * Table 31 of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf * @param attribute_list * The attribute string to parse, which may be modified in place. * The TPMA_OBJECT attributes set based on the attribute list. Only valid on true returns. * @return * true on success, false on error. */ bool tpm2_attr_util_obj_strtoattr(char *attribute_list, TPMA_OBJECT *objattrs); /** * Converts a numerical or friendly string described object attribute into the * TPMA_OBJECT. Similar to tpm2_alg_util_from_optarg(). * @param argvalue * Either a raw numeric for a UINT32 or a friendly name object attribute list * as in tpm2_attr_util_nv_strtoattr(). * @param objattrs * The converted bits for a TPMA_OBJECT * @return * true on success or false on error. */ bool tpm2_attr_util_obj_from_optarg(char *argvalue, TPMA_OBJECT *objattrs); /** * Converts a TPMA_NV structure to a friendly name style string. * @param nvattrs * The nvattrs to convert to nice name. * @return A string allocated with calloc(), callers shall use * free() to free it. The string is a null terminated text representation * of the TPMA_NV attributes. */ char *tpm2_attr_util_nv_attrtostr(TPMA_NV nvattrs); /** * Like tpm2_nv_util_obj_strtoattr() but converts TPMA_OBJECT attributes as defined in: * Table 31 of https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf * @param objattrs * The object parameters to convert to a name * @return * The name of the object attrs as a string that must be freed via free(). */ char *tpm2_attr_util_obj_attrtostr(TPMA_OBJECT objattrs); #endif /* LIB_TPM2_ATTR_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_auth_util.c000066400000000000000000000230531412464516500172650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_policy.h" #define HEX_PREFIX "hex:" #define HEX_PREFIX_LEN sizeof(HEX_PREFIX) - 1 #define STR_PREFIX "str:" #define STR_PREFIX_LEN sizeof(STR_PREFIX) - 1 #define SESSION_PREFIX "session:" #define SESSION_PREFIX_LEN sizeof(SESSION_PREFIX) - 1 #define FILE_PREFIX "file:" #define FILE_PREFIX_LEN sizeof(FILE_PREFIX) - 1 #define PCR_PREFIX "pcr:" #define PCR_PREFIX_LEN sizeof(PCR_PREFIX) - 1 static bool handle_hex_password(const char *password, TPM2B_AUTH *auth) { /* if it is hex, then skip the prefix */ password += HEX_PREFIX_LEN; auth->size = BUFFER_SIZE(typeof(*auth), buffer); int rc = tpm2_util_hex_to_byte_structure(password, &auth->size, auth->buffer); if (rc) { auth->size = 0; return false; } return true; } bool handle_str_password(const char *password, TPM2B_AUTH *auth) { /* str may or may not have the str: prefix */ bool is_str_prefix = !strncmp(password, STR_PREFIX, STR_PREFIX_LEN); if (is_str_prefix) { password += STR_PREFIX_LEN; } /* * Per the man page: * "a return value of size or more means that the output was truncated." */ size_t wrote = snprintf((char * )&auth->buffer, BUFFER_SIZE(typeof(*auth), buffer), "%s", password); if (wrote >= BUFFER_SIZE(typeof(*auth), buffer)) { auth->size = 0; return false; } auth->size = wrote; return true; } static bool handle_password(const char *password, TPM2B_AUTH *auth) { bool is_hex = !strncmp(password, HEX_PREFIX, HEX_PREFIX_LEN); if (is_hex) { return handle_hex_password(password, auth); } /* must be string, handle it */ return handle_str_password(password, auth); } static tool_rc start_hmac_session(ESYS_CONTEXT *ectx, TPM2B_AUTH *auth, tpm2_session **session) { tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_HMAC); if (!d) { LOG_ERR("oom"); return tool_rc_general_error; } tool_rc rc = tpm2_session_open(ectx, d, session); if (rc != tool_rc_success) { return rc; } tpm2_session_set_auth_value(*session, auth); return tool_rc_success; } static tool_rc handle_password_session(ESYS_CONTEXT *ectx, const char *password, tpm2_session **session) { TPM2B_AUTH auth = { 0 }; bool result = handle_password(password, &auth); if (!result) { return tool_rc_general_error; } return start_hmac_session(ectx, &auth, session); } static tool_rc handle_session(ESYS_CONTEXT *ectx, const char *path, tpm2_session **session) { TPM2B_AUTH auth = { 0 }; /* if it is session, then skip the prefix */ path += SESSION_PREFIX_LEN; /* Make a local copy for manipulation */ char tmp[PATH_MAX]; size_t len = snprintf(tmp, sizeof(tmp), "%s", path); if (len >= sizeof(tmp)) { LOG_ERR("Path truncated"); return tool_rc_general_error; } /* * Sessions can have an associated password/auth value denoted after * a + sign, ie session.ctx+foo, deal with it by * finding a +, splitting the string on it, and if * not a NULL byte after the +, use that as a password. */ char *password = strchr(tmp, '+'); if (password) { *password = '\0'; password++; if (*password) { bool result = handle_password(password, &auth); if (!result) { return tool_rc_general_error; } } } tool_rc rc = tpm2_session_restore(ectx, tmp, false, session); if (rc != tool_rc_success) { return rc; } tpm2_session_set_auth_value(*session, &auth); bool is_trial = tpm2_session_is_trial(*session); if (is_trial) { LOG_ERR("A trial session cannot be used to authenticate, " "Please use an hmac or policy session"); tpm2_session_close(session); return tool_rc_general_error; } return tool_rc_success; } static bool parse_pcr(const char *policy, char **pcr_str, char **raw_path) { char *split; policy += PCR_PREFIX_LEN; *pcr_str = NULL; *raw_path = NULL; /* completely empty PCR specification or just raw-pcr-file given */ if ((policy[0] == '\0') || (policy[0] == '=')) { return false; } *pcr_str = strdup(policy); if (!*pcr_str) { LOG_ERR("oom"); return false; } split = strchr(*pcr_str, '='); if (split) { split[0] = '\0'; *raw_path = split + 1; /* empty raw-pcr-file */ if (*raw_path[0] == '\0') { return false; } } return true; } static tool_rc handle_pcr(ESYS_CONTEXT *ectx, const char *policy, tpm2_session **session) { tool_rc rc = tool_rc_general_error; char *pcr_str, *raw_path; TPML_PCR_SELECTION pcrs; bool ret; ret = parse_pcr(policy, &pcr_str, &raw_path); if (!ret) { goto out; } ret = pcr_parse_selections(pcr_str, &pcrs); if (!ret) { goto out; } tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); if (!d) { LOG_ERR("oom"); goto out; } tpm2_session *s = NULL; tool_rc tmp_rc = tpm2_session_open(ectx, d, &s); if (tmp_rc != tool_rc_success) { LOG_ERR("Could not start tpm session"); rc = tmp_rc; goto out; } tmp_rc = tpm2_policy_build_pcr(ectx, s, raw_path, &pcrs, NULL); if (tmp_rc != tool_rc_success) { tpm2_session_close(&s); rc = tmp_rc; goto out; } *session = s; rc = tool_rc_success; out: free(pcr_str); return rc; } static tool_rc console_display_echo_control(bool echo) { struct termios console; int rc = tcgetattr(STDIN_FILENO, &console); if (rc) { return tool_rc_general_error; } if (echo) { console.c_lflag |= ECHO; } else { console.c_lflag &= ~((tcflag_t) ECHO); } rc = tcsetattr(STDIN_FILENO, TCSANOW, &console); if (rc) { return tool_rc_general_error; } return tool_rc_success; } static tool_rc handle_file(ESYS_CONTEXT *ectx, const char *path, tpm2_session **session) { path += FILE_PREFIX_LEN; path = strcmp("-", path) ? path : NULL; TPM2B_AUTH auth = { 0 }; UINT8 buffer[(sizeof(auth.buffer) * 2) + HEX_PREFIX_LEN + 1] = { 0 }; /* * If path is set or stdin is not a TTY, then read * from a path. Note: that "file:" will still go this * path and fail as path "" is not valid. */ bool is_a_tty = isatty(STDIN_FILENO); if (!is_a_tty || path) { UINT16 size = sizeof(buffer) - 1; bool ret = files_load_bytes_from_buffer_or_file_or_stdin(NULL, path, &size, buffer); if (!ret) { return tool_rc_general_error; } /* bash here strings and many commands add a trailing newline, if its stdin, kill the newline */ if (!path && buffer[size - 1] == '\n') { buffer[size - 1] = '\0'; } /* * It is a TTY and we're reading from stdin. * Prompt the user for the password with echoing * disabled. */ } else { tool_rc rc = console_display_echo_control(false); if (rc != tool_rc_success) { return rc; } printf("Enter Password: "); fflush(stdout); char *b = (char *) buffer; size_t size = sizeof(buffer) - 1; ssize_t read = getline(&b, &size, stdin); if (read < 0) { LOG_ERR("Could not get stdin, error: \"%s\"", strerror(errno)); } b[read - 1] = '\0'; rc = console_display_echo_control(true); if (rc != tool_rc_success || read < 0) { return tool_rc_general_error; } } /* from here the buffer has been populated with the password */ bool ret = handle_password((char *) buffer, &auth); if (!ret) { return tool_rc_general_error; } return start_hmac_session(ectx, &auth, session); } tool_rc tpm2_auth_util_from_optarg(ESYS_CONTEXT *ectx, const char *password, tpm2_session **session, bool is_restricted) { password = password ? password : ""; /* starts with session: */ bool is_session = !strncmp(password, SESSION_PREFIX, SESSION_PREFIX_LEN); if (is_session) { if (is_restricted) { LOG_ERR("Cannot specify password type \"session:\""); return tool_rc_general_error; } return handle_session(ectx, password, session); } /* starts with "file:" */ bool is_file = !strncmp(password, FILE_PREFIX, FILE_PREFIX_LEN); if (is_file) { return handle_file(ectx, password, session); } /* starts with pcr: */ bool is_pcr = !strncmp(password, PCR_PREFIX, PCR_PREFIX_LEN); if (is_pcr) { if (is_restricted) { LOG_ERR("Cannot specify password type \"pcr:\""); return tool_rc_general_error; } return handle_pcr(ectx, password, session); } /* must be a password */ return handle_password_session(ectx, password, session); } tool_rc tpm2_auth_util_get_shandle(ESYS_CONTEXT *ectx, ESYS_TR object, tpm2_session *session, ESYS_TR *out) { *out = tpm2_session_get_handle(session); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); return tpm2_tr_set_auth(ectx, object, auth); } tpm2-tools-5.2/lib/tpm2_auth_util.h000066400000000000000000000043621412464516500172740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_PASSWORD_UTIL_H_ #define SRC_PASSWORD_UTIL_H_ #include #include "tpm2_session.h" /** * Convert a password argument to a valid TPM2B_AUTH structure. Passwords can * be specified in two forms: string and hex-string and are identified by a * prefix of str: and hex: respectively. No prefix assumes the str form. * * For example, a string can be specified as: * "1234" * "str:1234" * * And a hexstring via: * "hex:1234abcd" * * Strings are copied verbatim to the TPM2B_AUTH buffer without the terminating NULL byte, * Hex strings differ only from strings in that they are converted to a byte array when * storing. At the end of storing, the size field is set to the size of bytes of the * password. * * If your password starts with a hex: prefix and you need to escape it, just use the string * prefix to escape it, like so: * "str:hex:password" * * @param ctx * Enhanced System API (ESAPI) context * @param password * The optarg containing the password string. * @param dest * The TPM2B_AUTH structure to copy the string into. * @ is_restricted * True if it is restricted to only password session data. * @return * tool_rc indicating status. */ tool_rc tpm2_auth_util_from_optarg(ESYS_CONTEXT *ctx, const char *password, tpm2_session **session, bool is_restricted); /** * Set up authorisation for a handle and return a session handle for use in * ESAPI calls. * * @param ectx * Enhanced System API (ESAPI) context * @param for_auth * The target handle which needs authorization setting up * @param auth * Auth command for the handle * @param session * Session for the handle * @param handle * The output handle for the session * @return * A tool_rc indicating status. */ tool_rc tpm2_auth_util_get_shandle(ESYS_CONTEXT *ectx, ESYS_TR for_auth, tpm2_session *session, ESYS_TR *handle); /** * Populate a string password in a TPM2B_AUTH structure. * * @param password * The string password or auth value. * @param auth * The TPM2B_AUTH structure to populate. * @return * Boolean indicating the success of the operation. */ bool handle_str_password(const char *password, TPM2B_AUTH *auth); #endif /* SRC_PASSWORD_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_capability.c000066400000000000000000000152031412464516500174060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "log.h" #include "tpm2.h" #include "tpm2_capability.h" #define APPEND_CAPABILITY_INFORMATION(capability, field, subfield, max_count) \ if (fetched_data->data.capability.count > max_count - property_count) { \ fetched_data->data.capability.count = max_count - property_count; \ } \ \ memmove(&(*capability_data)->data.capability.field[property_count], \ fetched_data->data.capability.field, \ fetched_data->data.capability.count * sizeof(fetched_data->data.capability.field[0])); \ property_count += fetched_data->data.capability.count; \ \ (*capability_data)->data.capability.count = property_count; \ \ if (more_data && property_count < count && fetched_data->data.capability.count) { \ property = (*capability_data)->data.capability.field[property_count - 1]subfield + 1; \ } else { \ more_data = false; \ } tool_rc tpm2_capability_get(ESYS_CONTEXT *ectx, TPM2_CAP capability, UINT32 property, UINT32 count, TPMS_CAPABILITY_DATA **capability_data) { TPMI_YES_NO more_data; UINT32 property_count = 0; *capability_data = NULL; do { /* fetch capability info */ TPMS_CAPABILITY_DATA *fetched_data = NULL; tool_rc rc = tpm2_get_capability(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, capability, property, count - property_count, &more_data, &fetched_data); LOG_INFO("GetCapability: capability: 0x%x, property: 0x%x", capability, property); if (rc != tool_rc_success) { if (*capability_data) { free(*capability_data); *capability_data = NULL; } return rc; } if (fetched_data->capability != capability) { LOG_ERR("TPM returned different capability than requested: 0x%x != " "0x%x", fetched_data->capability, capability); free(fetched_data); if (*capability_data) { free(*capability_data); *capability_data = NULL; } return tool_rc_general_error; } if (*capability_data == NULL) { /* reuse the TPM's result structure */ *capability_data = fetched_data; if (!more_data) { /* there won't be another iteration of the loop, just return the result unmodified */ return tool_rc_success; } } /* append the TPM's results to the initial structure, as long as there is still space left */ switch (capability) { case TPM2_CAP_ALGS: APPEND_CAPABILITY_INFORMATION(algorithms, algProperties, .alg, TPM2_MAX_CAP_ALGS); break; case TPM2_CAP_HANDLES: APPEND_CAPABILITY_INFORMATION(handles, handle,, TPM2_MAX_CAP_HANDLES); break; case TPM2_CAP_COMMANDS: APPEND_CAPABILITY_INFORMATION(command, commandAttributes,, TPM2_MAX_CAP_CC); /* workaround because tpm2-tss does not implement attribute commandIndex for TPMA_CC */ property &= TPMA_CC_COMMANDINDEX_MASK; break; case TPM2_CAP_PP_COMMANDS: APPEND_CAPABILITY_INFORMATION(ppCommands, commandCodes,, TPM2_MAX_CAP_CC); break; case TPM2_CAP_AUDIT_COMMANDS: APPEND_CAPABILITY_INFORMATION(auditCommands, commandCodes,, TPM2_MAX_CAP_CC); break; case TPM2_CAP_PCRS: APPEND_CAPABILITY_INFORMATION(assignedPCR, pcrSelections, .hash, TPM2_NUM_PCR_BANKS); break; case TPM2_CAP_TPM_PROPERTIES: APPEND_CAPABILITY_INFORMATION(tpmProperties, tpmProperty, .property, TPM2_MAX_TPM_PROPERTIES); break; case TPM2_CAP_PCR_PROPERTIES: APPEND_CAPABILITY_INFORMATION(pcrProperties, pcrProperty, .tag, TPM2_MAX_PCR_PROPERTIES); break; case TPM2_CAP_ECC_CURVES: APPEND_CAPABILITY_INFORMATION(eccCurves, eccCurves,, TPM2_MAX_ECC_CURVES); break; case TPM2_CAP_VENDOR_PROPERTY: APPEND_CAPABILITY_INFORMATION(intelPttProperty, property,, TPM2_MAX_PTT_PROPERTIES); break; default: LOG_ERR("Unsupported capability: 0x%x\n", capability); if (fetched_data != *capability_data) { free(fetched_data); } free(*capability_data); *capability_data = NULL; return tool_rc_general_error; } if (fetched_data != *capability_data) { free(fetched_data); } } while (more_data); return tool_rc_success; } tool_rc tpm2_capability_find_vacant_persistent_handle(ESYS_CONTEXT *ctx, bool is_platform, TPMI_DH_PERSISTENT *vacant) { TPMS_CAPABILITY_DATA *capability_data; bool handle_found = false; tool_rc rc = tpm2_capability_get(ctx, TPM2_CAP_HANDLES, TPM2_PERSISTENT_FIRST, TPM2_MAX_CAP_HANDLES, &capability_data); if (rc != tool_rc_success) { return rc; } UINT32 count = capability_data->data.handles.count; if (count == 0) { /* There aren't any persistent handles, so use the first */ *vacant = is_platform ? TPM2_PLATFORM_PERSISTENT : TPM2_PERSISTENT_FIRST; handle_found = true; } else if (count == TPM2_MAX_CAP_HANDLES) { /* All persistent handles are already in use */ goto out; } else if (count < TPM2_MAX_CAP_HANDLES) { /* * iterate over used handles to ensure we're selecting * the next available handle. * * Platform handles start at a higher hange */ UINT32 i; for (i = is_platform ? TPM2_PLATFORM_PERSISTENT : TPM2_PERSISTENT_FIRST; i <= (UINT32) TPM2_PERSISTENT_LAST; ++i) { bool inuse = false; UINT32 c; for (c = 0; c < count; ++c) { if (capability_data->data.handles.handle[c] == i) { inuse = true; break; } } if (!is_platform && i >= TPM2_PLATFORM_PERSISTENT) { break; } if (!inuse) { *vacant = i; handle_found = true; break; } } } out: free(capability_data); return handle_found ? tool_rc_success : tool_rc_general_error; } tpm2-tools-5.2/lib/tpm2_capability.h000066400000000000000000000023751412464516500174210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_CAPABILITY_H_ #define LIB_TPM2_CAPABILITY_H_ #include /** * Invokes GetCapability to retrieve the current value of a capability from the * TPM. * @param context * Enhanced system api (ESAPI) context * @param capability * the capability being requested from the TPM * @param property * property * @param count * maximum number of values to return * @param capability_data * capability data structure to populate * @return * tool_rc indicating status. */ tool_rc tpm2_capability_get(ESYS_CONTEXT *context, TPM2_CAP capability, UINT32 property, UINT32 count, TPMS_CAPABILITY_DATA **capability_data); /** * Attempts to find a vacant handle in the persistent handle namespace. * @param ctx * Enhanced System API (ESAPI) context * @param is_platform * true if the persistent handle should be in the persistent range allocated for * platform hierarchy, false otherwise. * @param vacant * the vacant handle found by the function if True returned * @return * tool_rc indicating status. */ tool_rc tpm2_capability_find_vacant_persistent_handle(ESYS_CONTEXT *ctx, bool is_platform, TPMI_DH_PERSISTENT *vacant); #endif /* LIB_TPM2_CAPABILITY_H_ */ tpm2-tools-5.2/lib/tpm2_cc_util.c000066400000000000000000000122421412464516500167070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "tpm2_cc_util.h" typedef struct cc_map cc_map; struct cc_map { TPM2_CC cc; const char *str; }; #define ADDCC(c) { .str = #c, .cc = c } static const cc_map _g_map[] = { ADDCC(TPM2_CC_NV_UndefineSpaceSpecial), ADDCC(TPM2_CC_EvictControl), ADDCC(TPM2_CC_HierarchyControl), ADDCC(TPM2_CC_NV_UndefineSpace), ADDCC(TPM2_CC_ChangeEPS), ADDCC(TPM2_CC_ChangePPS), ADDCC(TPM2_CC_Clear), ADDCC(TPM2_CC_ClearControl), ADDCC(TPM2_CC_ClockSet), ADDCC(TPM2_CC_HierarchyChangeAuth), ADDCC(TPM2_CC_NV_DefineSpace), ADDCC(TPM2_CC_PCR_Allocate), ADDCC(TPM2_CC_PCR_SetAuthPolicy), ADDCC(TPM2_CC_PP_Commands), ADDCC(TPM2_CC_SetPrimaryPolicy), ADDCC(TPM2_CC_FieldUpgradeStart), ADDCC(TPM2_CC_ClockRateAdjust), ADDCC(TPM2_CC_CreatePrimary), ADDCC(TPM2_CC_NV_GlobalWriteLock), ADDCC(TPM2_CC_GetCommandAuditDigest), ADDCC(TPM2_CC_NV_Increment), ADDCC(TPM2_CC_NV_SetBits), ADDCC(TPM2_CC_NV_Extend), ADDCC(TPM2_CC_NV_Write), ADDCC(TPM2_CC_NV_WriteLock), ADDCC(TPM2_CC_DictionaryAttackLockReset), ADDCC(TPM2_CC_DictionaryAttackParameters), ADDCC(TPM2_CC_NV_ChangeAuth), ADDCC(TPM2_CC_PCR_Event), ADDCC(TPM2_CC_PCR_Reset), ADDCC(TPM2_CC_SequenceComplete), ADDCC(TPM2_CC_SetAlgorithmSet), ADDCC(TPM2_CC_SetCommandCodeAuditStatus), ADDCC(TPM2_CC_FieldUpgradeData), ADDCC(TPM2_CC_IncrementalSelfTest), ADDCC(TPM2_CC_SelfTest), ADDCC(TPM2_CC_Startup), ADDCC(TPM2_CC_Shutdown), ADDCC(TPM2_CC_StirRandom), ADDCC(TPM2_CC_ActivateCredential), ADDCC(TPM2_CC_Certify), ADDCC(TPM2_CC_PolicyNV), ADDCC(TPM2_CC_CertifyCreation), ADDCC(TPM2_CC_Duplicate), ADDCC(TPM2_CC_GetTime), ADDCC(TPM2_CC_GetSessionAuditDigest), ADDCC(TPM2_CC_NV_Read), ADDCC(TPM2_CC_NV_ReadLock), ADDCC(TPM2_CC_ObjectChangeAuth), ADDCC(TPM2_CC_PolicySecret), ADDCC(TPM2_CC_Rewrap), ADDCC(TPM2_CC_Create), ADDCC(TPM2_CC_ECDH_ZGen), ADDCC(TPM2_CC_HMAC), ADDCC(TPM2_CC_Import), ADDCC(TPM2_CC_Load), ADDCC(TPM2_CC_Quote), ADDCC(TPM2_CC_RSA_Decrypt), ADDCC(TPM2_CC_HMAC_Start), ADDCC(TPM2_CC_SequenceUpdate), ADDCC(TPM2_CC_Sign), ADDCC(TPM2_CC_Unseal), ADDCC(TPM2_CC_PolicySigned), ADDCC(TPM2_CC_ContextLoad), ADDCC(TPM2_CC_ContextSave), ADDCC(TPM2_CC_ECDH_KeyGen), ADDCC(TPM2_CC_EncryptDecrypt), ADDCC(TPM2_CC_FlushContext), ADDCC(TPM2_CC_LoadExternal), ADDCC(TPM2_CC_MakeCredential), ADDCC(TPM2_CC_NV_ReadPublic), ADDCC(TPM2_CC_PolicyAuthorize), ADDCC(TPM2_CC_PolicyAuthValue), ADDCC(TPM2_CC_PolicyCommandCode), ADDCC(TPM2_CC_PolicyCounterTimer), ADDCC(TPM2_CC_PolicyCpHash), ADDCC(TPM2_CC_PolicyLocality), ADDCC(TPM2_CC_PolicyNameHash), ADDCC(TPM2_CC_PolicyOR), ADDCC(TPM2_CC_PolicyTicket), ADDCC(TPM2_CC_ReadPublic), ADDCC(TPM2_CC_RSA_Encrypt), ADDCC(TPM2_CC_StartAuthSession), ADDCC(TPM2_CC_VerifySignature), ADDCC(TPM2_CC_ECC_Parameters), ADDCC(TPM2_CC_FirmwareRead), ADDCC(TPM2_CC_GetCapability), ADDCC(TPM2_CC_GetRandom), ADDCC(TPM2_CC_GetTestResult), ADDCC(TPM2_CC_Hash), ADDCC(TPM2_CC_PCR_Read), ADDCC(TPM2_CC_PolicyPCR), ADDCC(TPM2_CC_PolicyRestart), ADDCC(TPM2_CC_ReadClock), ADDCC(TPM2_CC_PCR_Extend), ADDCC(TPM2_CC_PCR_SetAuthValue), ADDCC(TPM2_CC_NV_Certify), ADDCC(TPM2_CC_EventSequenceComplete), ADDCC(TPM2_CC_HashSequenceStart), ADDCC(TPM2_CC_PolicyPhysicalPresence), ADDCC(TPM2_CC_PolicyDuplicationSelect), ADDCC(TPM2_CC_PolicyGetDigest), ADDCC(TPM2_CC_TestParms), ADDCC(TPM2_CC_Commit), ADDCC(TPM2_CC_PolicyPassword), ADDCC(TPM2_CC_ZGen_2Phase), ADDCC(TPM2_CC_EC_Ephemeral), ADDCC(TPM2_CC_PolicyNvWritten), ADDCC(TPM2_CC_PolicyTemplate), ADDCC(TPM2_CC_CreateLoaded), ADDCC(TPM2_CC_PolicyAuthorizeNV), ADDCC(TPM2_CC_EncryptDecrypt2), ADDCC(TPM2_CC_AC_GetCapability), ADDCC(TPM2_CC_AC_Send), ADDCC(TPM2_CC_Policy_AC_SendSelect), ADDCC(TPM2_CC_Vendor_TCG_Test), }; bool tpm2_cc_util_from_str(const char *str, TPM2_CC *cc) { if (!str || !cc) { return false; } bool result = tpm2_util_string_to_uint32(str, cc); if (result) { return true; } size_t i; for (i = 0; i < ARRAY_LEN(_g_map); i++) { const cc_map *m = &_g_map[i]; if (!strcmp(str, m->str)) { *cc = m->cc; return true; } } LOG_ERR("Could not convert command-code to number, got: \"%s\"", str); return false; } const char *tpm2_cc_util_to_str(TPM2_CC cc) { size_t i; for (i = 0; i < ARRAY_LEN(_g_map); i++) { const cc_map *m = &_g_map[i]; if (m->cc == cc) { return m->str; } } /* we intentionally don't decode hex here so we don't have to keep * an internal buffer state that could be clobbered. Thus keeping it * reentrant and thread safe even though the tools never need thread * safety. * * DO NOT LOG ERROR as tpm2_getcap can have unknown commands and knows * how to deal with NULL returns. */ return NULL; } tpm2-tools-5.2/lib/tpm2_cc_util.h000066400000000000000000000015731412464516500167210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_CC_UTIL_H_ #define LIB_TPM2_CC_UTIL_H_ #include #include /** * Converts a string to a command code. * @param str * The string to convert. The string is either the macro name * of the command code provided by the tss2_tpm2_types.h header file or * a numerical string understood by strtoul() with a base of 0. * @param cc * The command code value. * @return * True if successful, false otherwise. */ bool tpm2_cc_util_from_str(const char *str, TPM2_CC *cc); /** * Given a command code, returns the name of the command as defined by the macro * names in tss2_tpm2_types.h. If the command is unknown, NULL is returned. * @param cc * The command to decode. * @return * A string or NULL. */ const char *tpm2_cc_util_to_str(TPM2_CC cc); #endif /* LIB_TPM2_CC_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_convert.c000066400000000000000000000532621412464516500167540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000L #include #else #include #include #include #endif #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public, tpm2_convert_pubkey_fmt format, const char *path); tpm2_convert_pcrs_output_fmt tpm2_convert_pcrs_output_fmt_from_optarg( const char *label) { if (strcasecmp(label, "values") == 0) { return pcrs_output_format_values; } else if (strcasecmp(label, "serialized") == 0) { return pcrs_output_format_serialized; } LOG_ERR("Invalid pcrs output format '%s' specified", label); return pcrs_output_format_err; } tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt_from_optarg(const char *label) { if (strcasecmp(label, "der") == 0) { return pubkey_format_der; } else if (strcasecmp(label, "pem") == 0) { return pubkey_format_pem; } else if (strcasecmp(label, "tss") == 0) { return pubkey_format_tss; } else if (strcasecmp(label, "tpmt") == 0) { return pubkey_format_tpmt; } LOG_ERR("Invalid public key output format '%s' specified", label); return pubkey_format_err; } tpm2_convert_sig_fmt tpm2_convert_sig_fmt_from_optarg(const char *label) { if (strcasecmp(label, "tss") == 0) { return signature_format_tss; } else if (strcasecmp(label, "plain") == 0) { return signature_format_plain; } LOG_ERR("Invalid signature output format '%s' specified", label); return signature_format_err; } static void print_ssl_error(const char *failed_action) { char errstr[256] = { 0 }; unsigned long errnum = ERR_get_error(); ERR_error_string_n(errnum, errstr, sizeof(errstr)); LOG_ERR("%s: %s", failed_action, errstr); } bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public, tpm2_convert_pubkey_fmt format, const char *path) { if (format == pubkey_format_der || format == pubkey_format_pem) { return tpm2_convert_pubkey_ssl(&public->publicArea, format, path); } else if (format == pubkey_format_tss) { return files_save_public(public, path); } else if (format == pubkey_format_tpmt) { return files_save_template(&public->publicArea, path); } LOG_ERR("Unsupported public key output format."); return false; } EVP_PKEY *convert_pubkey_RSA(TPMT_PUBLIC *public) { #if OPENSSL_VERSION_NUMBER < 0x30000000L RSA *rsa_key = NULL; #else OSSL_PARAM_BLD *build = NULL; OSSL_PARAM *params = NULL; EVP_PKEY_CTX *ctx = NULL; #endif BIGNUM *e = NULL, *n = NULL; EVP_PKEY *pkey = NULL; UINT32 exponent = (public->parameters).rsaDetail.exponent; if (exponent == 0) { exponent = 0x10001; } n = BN_bin2bn(public->unique.rsa.buffer, public->unique.rsa.size, NULL); if (!n) { print_ssl_error("Failed to convert data to SSL internal format"); goto error; } #if OPENSSL_VERSION_NUMBER < 0x30000000L rsa_key = RSA_new(); if (!rsa_key) { print_ssl_error("Failed to allocate OpenSSL RSA structure"); goto error; } e = BN_new(); if (!e) { print_ssl_error("Failed to convert data to SSL internal format"); goto error; } int rc = BN_set_word(e, exponent); if (!rc) { print_ssl_error("Failed to convert data to SSL internal format"); goto error; } rc = RSA_set0_key(rsa_key, n, e, NULL); if (!rc) { print_ssl_error("Failed to set RSA modulus and exponent components"); goto error; } /* modulus and exponent components are now owned by the RSA struct */ n = e = NULL; pkey = EVP_PKEY_new(); if (!pkey) { print_ssl_error("Failed to allocate OpenSSL EVP structure"); goto error; } rc = EVP_PKEY_assign_RSA(pkey, rsa_key); if (!rc) { print_ssl_error("Failed to set OpenSSL EVP structure"); EVP_PKEY_free(pkey); pkey = NULL; goto error; } /* rsa key is now owner by the EVP_PKEY struct */ rsa_key = NULL; #else build = OSSL_PARAM_BLD_new(); if (!build) { print_ssl_error("Failed to allocate OpenSSL parameters"); goto error; } int rc = OSSL_PARAM_BLD_push_BN(build, OSSL_PKEY_PARAM_RSA_N, n); if (!rc) { print_ssl_error("Failed to set RSA modulus"); goto error; } rc = OSSL_PARAM_BLD_push_uint32(build, OSSL_PKEY_PARAM_RSA_E, exponent); if (!rc) { print_ssl_error("Failed to set RSA exponent"); goto error; } params = OSSL_PARAM_BLD_to_param(build); if (!params) { print_ssl_error("Failed to build OpenSSL parameters"); goto error; } ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); if (!ctx) { print_ssl_error("Failed to allocate RSA key context"); goto error; } rc = EVP_PKEY_fromdata_init(ctx); if (rc <= 0) { print_ssl_error("Failed to initialize RSA key creation"); goto error; } rc = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params); if (rc <= 0) { print_ssl_error("Failed to create a RSA public key"); goto error; } #endif error: #if OPENSSL_VERSION_NUMBER < 0x30000000L RSA_free(rsa_key); #else EVP_PKEY_CTX_free(ctx); OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(build); #endif BN_free(n); BN_free(e); return pkey; } EVP_PKEY *convert_pubkey_ECC(TPMT_PUBLIC *public) { BIGNUM *x = NULL; BIGNUM *y = NULL; EC_POINT *point = NULL; EC_GROUP *group = NULL; #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *ec_key = NULL; #else OSSL_PARAM_BLD *build = NULL; OSSL_PARAM *params = NULL; EVP_PKEY_CTX *ctx = NULL; unsigned char *puboct = NULL; size_t bsize; #endif EVP_PKEY *pkey = NULL; TPMS_ECC_PARMS *tpm_ecc = &public->parameters.eccDetail; TPMS_ECC_POINT *tpm_point = &public->unique.ecc; /* * Set the affine coordinates for the point */ x = BN_bin2bn(tpm_point->x.buffer, tpm_point->x.size, NULL); if (!x) { print_ssl_error("Could not convert x coordinate to BN"); goto out; } y = BN_bin2bn(tpm_point->y.buffer, tpm_point->y.size, NULL); if (!y) { print_ssl_error("Could not convert y coordinate to BN"); goto out; } int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID); if (nid < 0) { goto out; } /* * Create a new point in the group, which is the public key. */ group = EC_GROUP_new_by_curve_name(nid); if (!group) { print_ssl_error("EC key missing group"); goto out; } point = EC_POINT_new(group); int rc = EC_POINT_set_affine_coordinates_tss(group, point, x, y, NULL); if (!rc) { print_ssl_error("Could not set affine coordinates"); goto out; } #if OPENSSL_VERSION_NUMBER < 0x30000000L /* * Create an empty EC key by the NID */ ec_key = EC_KEY_new_by_curve_name(nid); if (!ec_key) { print_ssl_error("Failed to create EC key from nid"); return false; } rc = EC_KEY_set_public_key(ec_key, point); if (!rc) { print_ssl_error("Could not set point as public key portion"); goto out; } if ((pkey = EVP_PKEY_new()) == NULL) { print_ssl_error("Failed to allocate OpenSSL EVP structure"); goto out; } rc = EVP_PKEY_assign_EC_KEY(pkey, ec_key); if (!rc) { print_ssl_error("Failed to set OpenSSL EVP structure"); EVP_PKEY_free(pkey); pkey = NULL; goto out; } /* rsa key is now owner by the EVP_PKEY struct */ ec_key = NULL; #else build = OSSL_PARAM_BLD_new(); if (!build) { print_ssl_error("Failed to allocate OpenSSL parameters"); goto out; } rc = OSSL_PARAM_BLD_push_utf8_string(build, OSSL_PKEY_PARAM_GROUP_NAME, (char *)OBJ_nid2sn(nid), 0); if (!rc) { print_ssl_error("Failed to set the EC group name"); goto out; } bsize = EC_POINT_point2buf(group, point, POINT_CONVERSION_COMPRESSED, &puboct, NULL); if (bsize == 0) { print_ssl_error("Failed compress the EC public key"); goto out; } rc = OSSL_PARAM_BLD_push_octet_string(build, OSSL_PKEY_PARAM_PUB_KEY, puboct, bsize); if (!rc) { print_ssl_error("Failed set the EC public key"); goto out; } params = OSSL_PARAM_BLD_to_param(build); if (!params) { print_ssl_error("Failed to build OpenSSL parameters"); goto out; } ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); if (!ctx) { print_ssl_error("Failed to allocate EC key context"); goto out; } rc = EVP_PKEY_fromdata_init(ctx); if (rc <= 0) { print_ssl_error("Failed to initialize EC key creation"); goto out; } rc = EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params); if (rc <= 0) { print_ssl_error("Failed to create a EC public key"); goto out; } #endif out: #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY_free(ec_key); #else EVP_PKEY_CTX_free(ctx); OSSL_PARAM_free(params); OSSL_PARAM_BLD_free(build); OPENSSL_free(puboct); #endif EC_POINT_free(point); EC_GROUP_free(group); BN_free(x); BN_free(y); return pkey; } static bool tpm2_convert_pubkey_bio(TPMT_PUBLIC *public, tpm2_convert_pubkey_fmt format, BIO *bio) { EVP_PKEY *pubkey = NULL; int ssl_res = 0; switch (public->type) { case TPM2_ALG_RSA: pubkey = convert_pubkey_RSA(public); break; case TPM2_ALG_ECC: pubkey = convert_pubkey_ECC(public); break; default: LOG_ERR("Unsupported key type for requested output format."); } if (pubkey == NULL) return false; switch (format) { case pubkey_format_pem: ssl_res = PEM_write_bio_PUBKEY(bio, pubkey); break; case pubkey_format_der: ssl_res = i2d_PUBKEY_bio(bio, pubkey); break; default: LOG_ERR("Invalid OpenSSL target format %d encountered", format); } EVP_PKEY_free(pubkey); if (ssl_res <= 0) { print_ssl_error("OpenSSL public key conversion failed"); return false; } return true; } static bool tpm2_convert_pubkey_ssl(TPMT_PUBLIC *public, tpm2_convert_pubkey_fmt format, const char *path) { BIO *bio = path ? BIO_new_file(path, "wb") : BIO_new_fp(stdout, BIO_NOCLOSE); if (!bio) { LOG_ERR("Failed to open public key output file '%s': %s", path ? path : "", ERR_error_string(ERR_get_error(), NULL)); return false; } bool result = tpm2_convert_pubkey_bio(public, format, bio); BIO_free(bio); return result; } bool tpm2_convert_sig_save(TPMT_SIGNATURE *signature, tpm2_convert_sig_fmt format, const char *path) { switch (format) { case signature_format_tss: return files_save_signature(signature, path); case signature_format_plain: { UINT8 *buffer; UINT16 size; buffer = tpm2_convert_sig(&size, signature); if (buffer == NULL) { return false; } bool ret = files_save_bytes_to_file(path, buffer, size); free(buffer); return ret; } default: LOG_ERR("Unsupported signature output format."); return false; } } /** * Parses the ASN1 format for an ECDSA Signature * * The ASN1 format for ECDSA signature is: https://www.ietf.org/rfc/rfc5480.txt * ECDSA-Sig-Value ::= SEQUENCE { r INTEGER, s INTEGER } * * @param path * @param ecdsa * @return */ static bool pop_ecdsa(const char *path, TPMS_SIGNATURE_ECDSA *ecdsa) { TPM2B_MAX_BUFFER buf = { .size = sizeof(buf.buffer) }; bool res = files_load_bytes_from_path(path, buf.buffer, &buf.size); if (!res) { return res; } int tag; int class; long len; const unsigned char *p = buf.buffer; int j = ASN1_get_object(&p, &len, &tag, &class, buf.size); if (!(j & V_ASN1_CONSTRUCTED)) { LOG_ERR("Expected ECDSA signature to start as ASN1 Constructed object"); return false; } if (tag != V_ASN1_SEQUENCE) { LOG_ERR("Expected ECDSA signature to be an ASN1 sequence"); return false; } /* * Get R */ TPM2B_ECC_PARAMETER *R = &ecdsa->signatureR; ASN1_INTEGER *r = d2i_ASN1_INTEGER(NULL, &p, len); if (!r) { LOG_ERR("oom"); return false; } memcpy(R->buffer, r->data, r->length); R->size = r->length; ASN1_INTEGER_free(r); /* * Get S */ TPM2B_ECC_PARAMETER *S = &ecdsa->signatureS; ASN1_INTEGER *s = d2i_ASN1_INTEGER(NULL, &p, len); if (!s) { LOG_ERR("oom"); return false; } memcpy(S->buffer, s->data, s->length); S->size = s->length; ASN1_INTEGER_free(s); return true; } static bool sig_load(const char *path, TPMI_ALG_SIG_SCHEME sig_alg, TPMI_ALG_HASH halg, TPMT_SIGNATURE *signature) { signature->sigAlg = sig_alg; bool res = false; switch (sig_alg) { case TPM2_ALG_RSASSA: signature->signature.rsassa.hash = halg; signature->signature.rsassa.sig.size = sizeof(signature->signature.rsassa.sig.buffer); res = files_load_bytes_from_path(path, signature->signature.rsassa.sig.buffer, &signature->signature.rsassa.sig.size); return res; case TPM2_ALG_RSAPSS: signature->signature.rsapss.hash = halg; signature->signature.rsapss.sig.size = sizeof(signature->signature.rsapss.sig.buffer); res = files_load_bytes_from_path(path, signature->signature.rsapss.sig.buffer, &signature->signature.rsapss.sig.size); return res; case TPM2_ALG_ECDSA: signature->signature.ecdsa.hash = halg; return pop_ecdsa(path, &signature->signature.ecdsa); default: LOG_ERR("Unsupported signature input format."); return false; } } bool tpm2_convert_sig_load(const char *path, tpm2_convert_sig_fmt format, TPMI_ALG_SIG_SCHEME sig_alg, TPMI_ALG_HASH halg, TPMT_SIGNATURE *signature) { switch (format) { case signature_format_tss: return files_load_signature(path, signature); case signature_format_plain: return sig_load(path, sig_alg, halg, signature); default: LOG_ERR("Unsupported signature input format."); return false; } } bool tpm2_convert_sig_load_plain(const char *path, TPM2B_MAX_BUFFER *signature, TPMI_ALG_HASH *halg) { /* * TSS signature need be read and converted to plain * * So load it up into the TPMT Structure */ TPMT_SIGNATURE tmp = { 0 }; bool ret = files_load_signature_silent(path, &tmp); if (!ret) { /* plain signatures are just used as is */ *halg = TPM2_ALG_NULL; signature->size = sizeof(signature->buffer); return files_load_bytes_from_path(path, signature->buffer, &signature->size); } *halg = tmp.signature.any.hashAlg; /* Then convert it to plain, but into a buffer */ UINT8 *buffer; UINT16 size; buffer = tpm2_convert_sig(&size, &tmp); if (buffer == NULL) { return false; } if (size > sizeof(signature->buffer)) { LOG_ERR("Signature size bigger than buffer, got: %u expected" " less than %zu", size, sizeof(signature->buffer)); free(buffer); return false; } signature->size = size; memcpy(signature->buffer, buffer, size); free(buffer); return true; } static UINT8 *extract_ecdsa(TPMS_SIGNATURE_ECDSA *ecdsa, UINT16 *size) { /* the DER encoded ECDSA signature */ unsigned char *buf = NULL; TPM2B_ECC_PARAMETER *R = &ecdsa->signatureR; TPM2B_ECC_PARAMETER *S = &ecdsa->signatureS; ECDSA_SIG *sig = ECDSA_SIG_new(); if (sig == NULL) { return NULL; } BIGNUM *bn_r = BN_bin2bn(R->buffer, R->size, NULL); if (!bn_r) { goto out; } BIGNUM *bn_s = BN_bin2bn(S->buffer, S->size, NULL); if (!bn_s) { BN_free(bn_r); goto out; } int rc = ECDSA_SIG_set0(sig, bn_r, bn_s); if (rc != 1) { BN_free(bn_r); BN_free(bn_s); goto out; } /* * r and s are now owned by the ecdsa signature no need * to free */ int len = i2d_ECDSA_SIG(sig, NULL); if (len <= 0) { goto out; } buf = malloc(len); if (!buf) { goto out; } unsigned char *pp = buf; len = i2d_ECDSA_SIG(sig, &pp); if (len <= 0) { free(buf); buf = NULL; goto out; } *size = len; /* success */ out: ECDSA_SIG_free(sig); return buf; } UINT8 *tpm2_convert_sig(UINT16 *size, TPMT_SIGNATURE *signature) { UINT8 *buffer = NULL; *size = 0; switch (signature->sigAlg) { case TPM2_ALG_RSASSA: *size = signature->signature.rsassa.sig.size; buffer = malloc(*size); if (!buffer) { goto nomem; } memcpy(buffer, signature->signature.rsassa.sig.buffer, *size); break; case TPM2_ALG_RSAPSS: *size = signature->signature.rsapss.sig.size; buffer = malloc(*size); if (!buffer) { goto nomem; } memcpy(buffer, signature->signature.rsapss.sig.buffer, *size); break; case TPM2_ALG_HMAC: { TPMU_HA *hmac_sig = &(signature->signature.hmac.digest); *size = tpm2_alg_util_get_hash_size(signature->signature.hmac.hashAlg); if (*size == 0) { LOG_ERR("Hash algorithm %d has 0 size", signature->signature.hmac.hashAlg); goto nomem; } buffer = malloc(*size); if (!buffer) { goto nomem; } memcpy(buffer, hmac_sig, *size); break; } case TPM2_ALG_ECDSA: { return extract_ecdsa(&signature->signature.ecdsa, size); } default: LOG_ERR("%s: unknown signature scheme: 0x%x", __func__, signature->sigAlg); return NULL; } return buffer; nomem: LOG_ERR("%s: couldn't allocate memory", __func__); return NULL; } bool tpm2_public_load_pkey(const char *path, EVP_PKEY **pkey) { bool result = false; BIO *bio = NULL; EVP_PKEY *p = NULL; /* * Order Matters. You must check for the smallest TSS size first, which * it the TPMT_PUBLIC as it's embedded in the TPM2B_PUBLIC. It's possible * to have valid TPMT's and have them parse as valid TPM2B_PUBLIC's (apparantly). * * If none of them convert, we try it as a plain signature. */ TPM2B_PUBLIC public = { 0 }; bool ret = files_load_template_silent(path, &public.publicArea); if (ret) { goto convert_to_pem; } ret = files_load_public_silent(path, &public); if (ret) { goto convert_to_pem; } /* not a tss format, just treat it as a pem file */ bio = BIO_new_file(path, "rb"); if (!bio) { LOG_ERR("Failed to open public key output file '%s': %s", path, ERR_error_string(ERR_get_error(), NULL)); return false; } /* not a tpm data structure, must be pem */ goto try_pem; convert_to_pem: bio = BIO_new(BIO_s_mem()); if (!bio) { LOG_ERR("Failed to allocate memory bio: %s", ERR_error_string(ERR_get_error(), NULL)); return false; } ret = tpm2_convert_pubkey_bio(&public.publicArea, pubkey_format_pem, bio); if (!ret) { goto out; } try_pem: p = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); if (!p) { LOG_ERR("Failed to convert public key from file '%s': %s", path, ERR_error_string(ERR_get_error(), NULL)); goto out; } *pkey = p; result = true; out: if (bio) { BIO_free(bio); } return result; } bool tpm2_base64_encode(BYTE *buffer, size_t buffer_length, char *base64) { unsigned char out[1024]; int outl; EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); EVP_EncodeInit(ctx); int rc = EVP_EncodeUpdate(ctx, out, &outl, buffer, buffer_length); if(rc < 0) { LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc); EVP_ENCODE_CTX_free(ctx); return false; } EVP_EncodeFinal(ctx, out, &outl); // no return value EVP_ENCODE_CTX_free(ctx); strcpy(base64, (char*) out); return true; } bool tpm2_base64_decode(char *base64, BYTE *buffer, size_t *buffer_length) { bool is_base64_bufferlen_valid = strlen(base64) > 1024 ? false : true; if (!is_base64_bufferlen_valid) { return false; } unsigned char base64u[1024]; memcpy(base64u, base64, strlen(base64)); EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); EVP_DecodeInit(ctx); unsigned char out[1024]; int outl; int rc = EVP_DecodeUpdate(ctx, out, &outl, base64u, strlen(base64)); if(rc < 0) { LOG_ERR("EVP_DecodeUpdate failed with %d\n", rc); EVP_ENCODE_CTX_free(ctx); return false; } *buffer_length = outl; rc = EVP_DecodeFinal(ctx, out, &outl); if(rc < 0) { LOG_ERR("EVP_DecodeFinal failed with %d\n", rc); EVP_ENCODE_CTX_free(ctx); return false; } EVP_ENCODE_CTX_free(ctx); *buffer_length += outl; memcpy(buffer, out, *buffer_length); return true; } tpm2-tools-5.2/lib/tpm2_convert.h000066400000000000000000000120471412464516500167550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef CONVERSION_H #define CONVERSION_H #include #include #include typedef enum tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt; enum tpm2_convert_pubkey_fmt { pubkey_format_tss, pubkey_format_pem, pubkey_format_der, pubkey_format_tpmt, pubkey_format_err }; typedef enum tpm2_convert_sig_fmt tpm2_convert_sig_fmt; enum tpm2_convert_sig_fmt { signature_format_tss, signature_format_plain, signature_format_err }; typedef enum tpm2_convert_pcrs_output_fmt tpm2_convert_pcrs_output_fmt; enum tpm2_convert_pcrs_output_fmt { pcrs_output_format_values, pcrs_output_format_serialized, pcrs_output_format_err }; /** * Parses the given command line PCRS file output format option string and * returns the corresponding pcrs_output_fmt enum value. * * LOG_ERR is used to communicate errors. * * @return * On error pcrs_output_format_err is returned. */ tpm2_convert_pcrs_output_fmt tpm2_convert_pcrs_output_fmt_from_optarg( const char *label); /** * Parses the given command line public key format option string and returns * the corresponding pubkey_format enum value. * * LOG_ERR is used to communicate errors. * * @return * On error pubkey_format_err is returned. */ tpm2_convert_pubkey_fmt tpm2_convert_pubkey_fmt_from_optarg(const char *label); /** * Converts the given public key structure into the requested target format * and writes the result to the given file system path. * * LOG_ERR is used to communicate errors. */ bool tpm2_convert_pubkey_save(TPM2B_PUBLIC *public, tpm2_convert_pubkey_fmt format, const char *path); /** * Converts the given RSA public key structure into the EVP_PKEY. * * @param public * TPM2 public key structure structure. * @return * OpenSSL key structure, or NULL on error. */ EVP_PKEY *convert_pubkey_RSA(TPMT_PUBLIC *public); /** * Converts the given ECC public key structure into the EVP_PKEY. * * @param public * TPM2 public key structure structure. * @return * OpenSSL key structure, or NULL on error. */ EVP_PKEY *convert_pubkey_ECC(TPMT_PUBLIC *public); /** * Parses the given command line signature format option string and returns * the corresponding signature_format enum value. * * LOG_ERR is used to communicate errors. * * @return * On error signature_format_err is returned. */ tpm2_convert_sig_fmt tpm2_convert_sig_fmt_from_optarg(const char *label); /** * Converts the given signature data into the requested target format and * writes the result to the given file system path. * * LOG_ERR is used to communicate errors. */ bool tpm2_convert_sig_save(TPMT_SIGNATURE *signature, tpm2_convert_sig_fmt format, const char *path); /** * Like tpm2_convert_save with the "plain" signature option. * * @param size * The size of the signature buffer. * @param signature * The signature to convert. * @return * NULL on error or a buffer of size bytes to be freed by the caller * via free(2). */ UINT8 *tpm2_convert_sig(UINT16 *size, TPMT_SIGNATURE *signature); /** * Load a signature from path and convert the format * @param path * The path to load the signature from. * @param format * The tss signature format * @param sig_alg * The algorithm used for the signature. Only RSASSA (RSA PKCS1.5) signatures accepted. * @param halg * The hashing algorithm used. * @param signature * The signature structure to output too. * @return * true on success, false on error. */ bool tpm2_convert_sig_load(const char *path, tpm2_convert_sig_fmt format, TPMI_ALG_SIG_SCHEME sig_alg, TPMI_ALG_HASH halg, TPMT_SIGNATURE *signature); /** * Given a file, loads up the plain format of the signature. Probing to determine * if its a TSS buffer (using libmu errors as the detector) or a plain OSSL style * signature. * into a buffer. * @param path * The file path containing the signature. * @param signature * The plain signature bytes. * @param halg: * If the signature scheme is *tss* also provide the hash algorithm, else * set it to TPM2_ALG_NULL. * @return * true on success, false on error. */ bool tpm2_convert_sig_load_plain(const char *path, TPM2B_MAX_BUFFER *signature, TPMI_ALG_HASH *halg); bool tpm2_public_load_pkey(const char *path, EVP_PKEY **pkey); /** * Encode a binary buffer to a Base64-encoded String. * @param buffer * The binary buffer. * @param buffer_length: * The length of the binary buffer. * @param base64 * The resulting Base64-encoded String. * @return * true on success, false on error. */ bool tpm2_base64_encode(BYTE *buffer, size_t buffer_length, char *base64); /** * Decode a Base64-encoded String to a binary buffer. * @param base64 * The Base64-encoded String. * @param buffer * The resulting binary buffer, valid on success. * @param buffer_length: * The length of the resulting binary buffer, valid on success. * @return * true on success, false on error. */ bool tpm2_base64_decode(char *base64, BYTE *buffer, size_t *buffer_length); #endif /* CONVERSION_H */ tpm2-tools-5.2/lib/tpm2_ctx_mgmt.c000066400000000000000000000015161412464516500171110ustar00rootroot00000000000000#include "log.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_ctx_mgmt.h" tool_rc tpm2_ctx_mgmt_evictcontrol(ESYS_CONTEXT *ectx, ESYS_TR auth, tpm2_session *sess, ESYS_TR objhandle, TPMI_DH_PERSISTENT phandle, ESYS_TR *out_tr) { ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, auth, sess, &shandle1); if (rc != tool_rc_success) { return rc; } ESYS_TR out_handle; TSS2_RC rval = Esys_EvictControl(ectx, auth, objhandle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, phandle, &out_handle); if (rval != TSS2_RC_SUCCESS) { LOG_PERR(Esys_EvictControl, rval); return tool_rc_from_tpm(rval); } if (out_tr) { *out_tr = out_handle; return tool_rc_success; } return tpm2_close(ectx, &out_handle); } tpm2-tools-5.2/lib/tpm2_ctx_mgmt.h000066400000000000000000000015541412464516500171200ustar00rootroot00000000000000#ifndef LIB_TPM2_CTX_MGMT_H_ #define LIB_TPM2_CTX_MGMT_H_ #include "tpm2_session.h" /** * Invokes evictcontrol for manipulating the persistence of loaded * objects in TPM memory. * @param context * The Enhanced System API (ESAPI) context * @param auth * The authorisation hierarchy, either TPM2_RH_OWNER or TPM2_RH_PLATFORM * @param sdata * The authorization data for auth. * @param objhandle * The object handle of a loaded object to manipulate. * @param phandle * The handle to persist objhandle at, if objhandle is transient. * @param out_tr * Optional. The ESYS_TR handle representing objhandle. * @return * tool_rc indicating status. */ tool_rc tpm2_ctx_mgmt_evictcontrol(ESYS_CONTEXT *context, ESYS_TR auth, tpm2_session *sess, ESYS_TR objhandle, TPMI_DH_PERSISTENT phandle, ESYS_TR *out_tr); #endif /* LIB_TPM2_CTX_MGMT_H_ */ tpm2-tools-5.2/lib/tpm2_errata.c000066400000000000000000000150071412464516500165450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "log.h" #include "tpm2_errata.h" #include "tpm2_capability.h" struct tpm2_errata_desc { UINT32 spec_level; /* spec level */ UINT32 spec_rev; /* spec revision */ UINT32 errata_ver; /* errata version */ void (*fixup)(va_list *ap); /* errata correction handler */ const char *name; /* full section name in errata doc */ }; /* * Published spec and errata information. * * Note that TPM2_PT_YEAR and TPM2_PT_DAY_OF_YEAR retrieved * from capability query only have the values of the * release date of the specification if the TPM does not * implement an errata. So the spec info are also given. */ static struct tpm2_errata_info { UINT32 spec_level; UINT32 spec_rev; UINT32 errata_ver; UINT32 year; UINT32 day_of_year; } known_errata_info[] = { /* Specification Revision 1.16 October 30, 2014 */ { 00, 116, 000, 2014, 303 }, /* Errata Version 1.2 February 16, 2015 */ { 00, 116, 120, 2015, 4 }, /* Errata Version 1.3 June 16, 2015 */ { 00, 116, 130, 2015, 167 }, /* Errata Version 1.4 January 15, 2016 */ { 00, 116, 140, 2016, 15 }, /* Errata Version 1.5 September 21, 2016 */ { 00, 116, 150, 2016, 265 }, /* Specification Revision 1.38 September 29, 2016 */ { 00, 138, 000, 2016, 273 }, /* Errata Version 1.0 January 16, 2017 */ { 00, 138, 100, 2017, 16 }, /* Errata Version 1.1 March 2, 2017 */ { 00, 138, 110, 2017, 61 }, }; static struct tpm2_errata_info *this_errata_info; static void fixup_sign_decrypt_attribute_encoding(va_list *ap); /* * Beware of that each record contains the first errata * version with the corresponding correction. This rule * allows errata_match() to function properly. */ static struct tpm2_errata_desc errata_desc_list[] = { [SPEC_116_ERRATA_2_7] = { .spec_level = 00, .spec_rev = 116, .errata_ver = 120, .fixup = fixup_sign_decrypt_attribute_encoding, .name = "Sign/decrypt attribute encoding", }, /* * Append the new errata descriptor here. */ }; static bool errata_match(struct tpm2_errata_desc *errata); static struct tpm2_errata_desc *errata_query(tpm2_errata_index_t index); /* * Request an errata correction. * @index: the errata to be queried. * * This function requests an errata correction to work * around a known issue well documented in errata doc. * If the request is valid and known, the queried errata * will be applied by the corresponding pre-defined errata * correction handler. The fixup process is transparent to * the callers so there is no return values. Any tools can * call this function to apply an errata if necessary. * * Return value: * N/A */ void tpm2_errata_fixup(tpm2_errata_index_t index, ...) { struct tpm2_errata_desc *errata; /* * There was no match against the TPMs details to a * known errata. */ if (!this_errata_info) { return; } /* Look up what errata the caller wants us to fix. */ errata = errata_query(index); if (!errata) { return; } /* * Check to see if that errata matches the tpm's * information and thus needs to be applied. */ bool res = errata_match(errata); if (res == false) { return; } va_list ap; va_start(ap, index); errata->fixup(&ap); va_end(ap); LOG_INFO("Errata %s applied", errata->name); } static void process(TPMS_CAPABILITY_DATA *capability_data) { /* Distinguish current spec level 0 */ UINT32 spec_level = -1; UINT32 spec_rev = 0; UINT32 day_of_year = 0; UINT32 year = 0; TPML_TAGGED_TPM_PROPERTY *properties = &capability_data->data.tpmProperties; size_t i; for (i = 0; i < properties->count; ++i) { TPMS_TAGGED_PROPERTY *property = properties->tpmProperty + i; if (property->property == TPM2_PT_LEVEL) { spec_level = property->value; } else if (property->property == TPM2_PT_REVISION) { spec_rev = property->value; } else if (property->property == TPM2_PT_DAY_OF_YEAR) { day_of_year = property->value; } else if (property->property == TPM2_PT_YEAR) { year = property->value; /* Short circuit because this is the last item we need */ break; } else if (property->property > TPM2_PT_YEAR) { break; } } if (!spec_rev || !day_of_year || !year) { LOG_WARN("Invalid TPM_SPEC parameter"); return; } /* Determine the TPM spec and errata */ for (i = 0; i < ARRAY_LEN(known_errata_info); ++i) { if (known_errata_info[i].day_of_year == day_of_year && known_errata_info[i].year == year && known_errata_info[i].spec_rev == spec_rev && known_errata_info[i].spec_level == spec_level) { this_errata_info = known_errata_info + i; LOG_INFO("TPM_SPEC: spec level %d, spec rev %f, errata ver %f", this_errata_info->spec_level, (float )this_errata_info->spec_rev / 100, (float )this_errata_info->errata_ver / 100); return; } } LOG_INFO("Unknown TPM_SPEC. spec_level: %d, spec_rev: 0x%x, " "year: %d, day_of_year: %d", spec_level, spec_rev, year, day_of_year); } void tpm2_errata_init(ESYS_CONTEXT *ctx) { TPMS_CAPABILITY_DATA *capability_data; tool_rc rc = tpm2_capability_get(ctx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_LEVEL, TPM2_PT_YEAR - TPM2_PT_LEVEL + 1, &capability_data); if (rc != tool_rc_success) { LOG_ERR("Failed to GetCapability: capability: 0x%x, property: 0x%x, ", TPM2_CAP_TPM_PROPERTIES, TPM2_PT_LEVEL); return; } process(capability_data); free(capability_data); } static void fixup_sign_decrypt_attribute_encoding(va_list *ap) { TPMA_OBJECT *attrs = va_arg(*ap, TPMA_OBJECT *); *attrs &= ~TPMA_OBJECT_SIGN_ENCRYPT; } static bool errata_match(struct tpm2_errata_desc *errata) { return errata->errata_ver > this_errata_info->errata_ver && errata->spec_rev >= this_errata_info->spec_rev && errata->spec_level == this_errata_info->spec_level; } static struct tpm2_errata_desc *errata_query(tpm2_errata_index_t index) { if ((size_t) index >= ARRAY_LEN(errata_desc_list)) { LOG_WARN("Invalid errata index queried: %u", (unsigned int )index); return NULL; } return &errata_desc_list[index]; } tpm2-tools-5.2/lib/tpm2_errata.h000066400000000000000000000022651412464516500165540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TPM2_ERRATA_H #define TPM2_ERRATA_H #include #include /* * Errata index pattern: * spec version + the section number in the errata doc * * Note that it is unnecessary to describe errata version * because the section number should be kept consistent * across all errata versions for a specific spec revision. */ typedef enum { SPEC_116_ERRATA_2_7, } tpm2_errata_index_t; /** * Initialize errata subsystem * * @param ctx * ESAPI context to be queried. */ void tpm2_errata_init(ESYS_CONTEXT *ctx); /** * Request an errata correction for a specific errata version. * @param index * the errata to be queried. * * This function requests an errata correction to work * around a known issue well documented in errata doc. * If the request is valid and known, the queried errata * will be applied by the corresponding pre-defined errata * correction handler. The fixup process is transparent to * the callers so there is no return values. Any tools can * call this function to apply an errata if necessary. */ void tpm2_errata_fixup(tpm2_errata_index_t index, ...); #endif /* TPM2_ERRATA_H */ tpm2-tools-5.2/lib/tpm2_eventlog.c000066400000000000000000000441041412464516500171120ustar00rootroot00000000000000#include #include #include #include #include "log.h" #include "efi_event.h" #include "tpm2_alg_util.h" #include "tpm2_eventlog.h" #include "tpm2_openssl.h" bool digest2_accumulator_callback(TCG_DIGEST2 const *digest, size_t size, void *data){ if (digest == NULL || data == NULL) { LOG_ERR("neither parameter may be NULL"); return false; } size_t *accumulator = (size_t*)data; *accumulator += sizeof(*digest) + size; return true; } /* * Invoke callback function for each TCG_DIGEST2 structure in the provided * TCG_EVENT_HEADER2. The callback function is only invoked if this function * is first able to determine that the provided buffer is large enough to * hold the digest. The size of the digest is passed to the callback in the * 'size' parameter. */ bool foreach_digest2(tpm2_eventlog_context *ctx, unsigned pcr_index, TCG_DIGEST2 const *digest, size_t count, size_t size) { if (digest == NULL) { LOG_ERR("digest cannot be NULL"); return false; } /* Because pcr_index is used for array indexing and bit-shift operations it is 1 less than the max value */ if (pcr_index > (TPM2_MAX_PCRS - 1)) { LOG_ERR("PCR Index %d is out of bounds for max available PCRS %d", pcr_index, TPM2_MAX_PCRS); return false; } bool ret = true; size_t i; for (i = 0; i < count; ++i) { if (size < sizeof(*digest)) { LOG_ERR("insufficient size for digest header"); return false; } const TPMI_ALG_HASH alg = digest->AlgorithmId; const size_t alg_size = tpm2_alg_util_get_hash_size(alg); if (size < sizeof(*digest) + alg_size) { LOG_ERR("insufficient size for digest buffer"); return false; } uint8_t *pcr = NULL; if (alg == TPM2_ALG_SHA1) { pcr = ctx->sha1_pcrs[pcr_index]; ctx->sha1_used |= (1 << pcr_index); } else if (alg == TPM2_ALG_SHA256) { pcr = ctx->sha256_pcrs[pcr_index]; ctx->sha256_used |= (1 << pcr_index); } else if (alg == TPM2_ALG_SHA384) { pcr = ctx->sha384_pcrs[pcr_index]; ctx->sha384_used |= (1 << pcr_index); } else if (alg == TPM2_ALG_SHA512) { pcr = ctx->sha512_pcrs[pcr_index]; ctx->sha512_used |= (1 << pcr_index); } else if (alg == TPM2_ALG_SM3_256) { pcr = ctx->sm3_256_pcrs[pcr_index]; ctx->sm3_256_used |= (1 << pcr_index); } else { LOG_WARN("PCR%d algorithm %d unsupported", pcr_index, alg); } if (pcr && !tpm2_openssl_pcr_extend(alg, pcr, digest->Digest, alg_size)) { LOG_ERR("PCR%d extend failed", pcr_index); return false; } if (ctx->digest2_cb != NULL) { ret = ctx->digest2_cb(digest, alg_size, ctx->data); if (!ret) { LOG_ERR("callback failed for digest at %p with size %zu", digest, alg_size); break; } } size -= sizeof(*digest) + alg_size; digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size); } return ret; } /* * given the provided event type, parse event to ensure the structure / data * in the buffer doesn't exceed the buffer size */ bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) { switch (type) { /* TCG PC Client FPF section 9.2.6 */ case EV_EFI_VARIABLE_DRIVER_CONFIG: case EV_EFI_VARIABLE_BOOT: case EV_EFI_VARIABLE_AUTHORITY: { UEFI_VARIABLE_DATA *data = (UEFI_VARIABLE_DATA*)event->Event; if (event->EventSize < sizeof(*data)) { LOG_ERR("size is insufficient for UEFI variable data"); return false; } if (event->EventSize < sizeof(*data) + data->UnicodeNameLength * sizeof(UTF16_CHAR) + data->VariableDataLength) { LOG_ERR("size is insufficient for UEFI variable data"); return false; } } break; /* TCG PC Client FPF section 2.3.4.1 and 9.4.1 */ case EV_POST_CODE: // the event is a string, so there are no length requirements. break; /* TCG PC Client FPF section 9.2.5 */ case EV_S_CRTM_CONTENTS: case EV_EFI_PLATFORM_FIRMWARE_BLOB: { UEFI_PLATFORM_FIRMWARE_BLOB *data = (UEFI_PLATFORM_FIRMWARE_BLOB*)event->Event; UNUSED(data); if (event->EventSize < sizeof(*data)) { LOG_ERR("size is insufficient for UEFI FW blob data"); return false; } } break; case EV_EFI_BOOT_SERVICES_APPLICATION: case EV_EFI_BOOT_SERVICES_DRIVER: case EV_EFI_RUNTIME_SERVICES_DRIVER: { UEFI_IMAGE_LOAD_EVENT *data = (UEFI_IMAGE_LOAD_EVENT*)event->Event; UNUSED(data); if (event->EventSize < sizeof(*data)) { LOG_ERR("size is insufficient for UEFI image load event"); return false; } /* what about the device path? */ } break; } return true; } /* * parse event structure, including header, digests and event buffer ensuring * it all fits within the provided buffer (buf_size). */ bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, size_t *event_size, size_t *digests_size) { bool ret; if (buf_size < sizeof(*eventhdr)) { LOG_ERR("corrupted log, insufficient size for event header: %zu", buf_size); return false; } *event_size = sizeof(*eventhdr); tpm2_eventlog_context ctx = { .data = digests_size, .digest2_cb = digest2_accumulator_callback, }; ret = foreach_digest2(&ctx, eventhdr->PCRIndex, eventhdr->Digests, eventhdr->DigestCount, buf_size - sizeof(*eventhdr)); if (ret != true) { return false; } *event_size += *digests_size; TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)eventhdr + *event_size); if (buf_size < *event_size + sizeof(*event)) { LOG_ERR("corrupted log: size insufficient for EventSize"); return false; } *event_size += sizeof(*event); if (buf_size < *event_size + event->EventSize) { LOG_ERR("size insufficient for event data"); return false; } *event_size += event->EventSize; return true; } bool parse_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *event, size_t size, size_t *event_size) { uint8_t *pcr = NULL; /* enough size for the 1.2 event structure */ if (size < sizeof(*event)) { LOG_ERR("insufficient size for SpecID event header"); return false; } *event_size = sizeof(*event); pcr = ctx->sha1_pcrs[ event->pcrIndex]; if (pcr) { tpm2_openssl_pcr_extend(TPM2_ALG_SHA1, pcr, &event->digest[0], 20); ctx->sha1_used |= (1 << event->pcrIndex); } /* buffer size must be sufficient to hold event and event data */ if (size < sizeof(*event) + (sizeof(event->event[0]) * event->eventDataSize)) { LOG_ERR("insufficient size for SpecID event data"); return false; } *event_size += event->eventDataSize; return true; } bool foreach_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *eventhdr_start, size_t size) { if (eventhdr_start == NULL) { LOG_ERR("invalid parameter"); return false; } if (size == 0) { return true; } TCG_EVENT const *eventhdr; size_t event_size; bool ret; for (eventhdr = eventhdr_start, event_size = 0; size > 0; eventhdr = (TCG_EVENT*)((uintptr_t)eventhdr + event_size), size -= event_size) { ret = parse_sha1_log_event(ctx, eventhdr, size, &event_size); if (!ret) { return ret; } TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)&eventhdr->eventDataSize); /* event header callback */ if (ctx->log_eventhdr_cb != NULL) { ret = ctx->log_eventhdr_cb(eventhdr, event_size, ctx->data); if (ret != true) { return false; } } ret = parse_event2body(event, eventhdr->eventType); if (ret != true) { return ret; } /* event data callback */ if (ctx->event2_cb != NULL) { ret = ctx->event2_cb(event, eventhdr->eventType, ctx->data, ctx->eventlog_version); if (ret != true) { return false; } } } return true; } /* * For event types where digest can be verified from their event payload, * perform verification to ensure event payload was not tempered */ bool verify_digests(size_t eventnum, TCG_EVENT_HEADER2 const *eventhdr, TCG_EVENT2 *event) { size_t i; TCG_DIGEST2 const *digest = eventhdr->Digests; UINT32 digest_count = eventhdr->DigestCount; UINT32 event_type = eventhdr->EventType; switch (event_type) { /* Digests of these event types are calculated directly from event->Event, thus can be verified */ case EV_S_CRTM_VERSION: case EV_SEPARATOR: case EV_EFI_VARIABLE_DRIVER_CONFIG: case EV_EFI_GPT_EVENT: for (i = 0; i < digest_count; i++) { TPMI_ALG_HASH alg = digest->AlgorithmId; TPM2B_DIGEST calc_digest; bool result = tpm2_openssl_hash_compute_data(alg, event->Event, event->EventSize, &calc_digest); if (!result) { LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1); return false; } size_t alg_size = tpm2_alg_util_get_hash_size(alg); if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) { LOG_WARN("Event %zu's digest does not match its payload", eventnum - 1); return false; } digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size); } break; /* Shim and grub use this event type for various tasks */ case EV_IPL: /* PCR9: used to measure loaded kernel and initramfs images which cannot be verified from eventlog alone */ if (eventhdr->PCRIndex == 9) { return true; } /* PCR14: used to measure MokList, MokListX, and MokSBState which cannot be verified from eventlog alone */ if (eventhdr->PCRIndex == 14) { return true; } /* PCR8: used to measure grub and kernel command line */ if (eventhdr->PCRIndex != 8) { LOG_WARN("Event %zu is unexpectedly not extending either PCR 8, 9, or 14", eventnum - 1); return false; } /* Digest is applied on the string between "^[a-zA-Z_]+:? " and EOL, * including or excluding the trailing NULL character */ for (i = 0; i < digest_count; i++) { size_t j; for (j = 0; j < event->EventSize; j++) { if (event->Event[j] == ' ') break; } if (j + 1 >= event->EventSize || event->Event[event->EventSize - 1] != '\0') { LOG_WARN("Event %zu's event data is in unexpected format", eventnum - 1); return false; } TPM2B_DIGEST calc_digest; TPMI_ALG_HASH alg = digest->AlgorithmId; /* First try to calculate the hash excluding the trailing \0 */ bool result = tpm2_openssl_hash_compute_data(alg, event->Event + (j + 1), event->EventSize - (j + 2), &calc_digest); if (!result) { LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1); return false; } size_t alg_size = tpm2_alg_util_get_hash_size(alg); if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) { /* Next try to calculate the hash including the trailing \0 */ bool result = tpm2_openssl_hash_compute_data(alg, event->Event + (j + 1), event->EventSize - (j + 1), &calc_digest); if (!result) { LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1); return false; } if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) { LOG_WARN("Event %zu's digest does not match its payload", eventnum - 1); return false; } } digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size); } break; } return true; } bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhdr_start, size_t size) { if (eventhdr_start == NULL) { LOG_ERR("invalid parameter"); return false; } if (size == 0) { return true; } TCG_EVENT_HEADER2 const *eventhdr; size_t event_size; bool ret; for (eventhdr = eventhdr_start, event_size = 0; size > 0; eventhdr = (TCG_EVENT_HEADER2*)((uintptr_t)eventhdr + event_size), size -= event_size) { size_t digests_size = 0; ret = parse_event2(eventhdr, size, &event_size, &digests_size); if (!ret) { return ret; } TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)eventhdr->Digests + digests_size); /* event header callback */ if (ctx->event2hdr_cb != NULL) { ret = ctx->event2hdr_cb(eventhdr, event_size, ctx->data); if (ret != true) { return false; } } /* digest callback foreach digest */ ret = foreach_digest2(ctx, eventhdr->PCRIndex, eventhdr->Digests, eventhdr->DigestCount, digests_size); if (ret != true) { return false; } ret = parse_event2body(event, eventhdr->EventType); if (ret != true) { return ret; } /* digest verification */ if (ctx->data != 0) { verify_digests(*(size_t*)ctx->data, eventhdr, event); } /* event data callback */ if (ctx->event2_cb != NULL) { ret = ctx->event2_cb(event, eventhdr->EventType, ctx->data, ctx->eventlog_version); if (ret != true) { return false; } } } return true; } bool specid_event(TCG_EVENT const *event, size_t size, TCG_EVENT_HEADER2 **next) { /* enough size for the 1.2 event structure */ if (size < sizeof(*event)) { LOG_ERR("insufficient size for SpecID event header"); return false; } if (event->eventType != EV_NO_ACTION) { LOG_ERR("SpecID eventType must be EV_NO_ACTION"); return false; } if (event->pcrIndex != 0) { LOG_ERR("bad pcrIndex for EV_NO_ACTION event"); return false; } size_t i; for (i = 0; i < sizeof(event->digest); ++i) { if (event->digest[i] != 0) { LOG_ERR("SpecID digest data malformed"); return false; } } /* eventDataSize must be sufficient to hold the specid event */ if (event->eventDataSize < sizeof(TCG_SPECID_EVENT)) { LOG_ERR("invalid eventDataSize in specid event"); return false; } /* buffer size must be sufficient to hold event and event data */ if (size < sizeof(*event) + (sizeof(event->event[0]) * event->eventDataSize)) { LOG_ERR("insufficient size for SpecID event data"); return false; } /* specid event must have 1 or more algorithms */ TCG_SPECID_EVENT *event_specid = (TCG_SPECID_EVENT*)event->event; if (event_specid->numberOfAlgorithms == 0) { LOG_ERR("numberOfAlgorithms is invalid, may not be 0"); return false; } /* buffer size must be sufficient to hold event, specid event & algs */ if (size < sizeof(*event) + sizeof(*event_specid) + sizeof(event_specid->digestSizes[0]) * event_specid->numberOfAlgorithms) { LOG_ERR("insufficient size for SpecID algorithms"); return false; } /* size must be sufficient for event, specid, algs & vendor stuff */ if (size < sizeof(*event) + sizeof(*event_specid) + sizeof(event_specid->digestSizes[0]) * event_specid->numberOfAlgorithms + sizeof(TCG_VENDOR_INFO)) { LOG_ERR("insufficient size for VendorStuff"); return false; } TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)((uintptr_t)event_specid->digestSizes + sizeof(*event_specid->digestSizes) * event_specid->numberOfAlgorithms); /* size must be sufficient for vendorInfo */ if (size < sizeof(*event) + sizeof(*event_specid) + sizeof(event_specid->digestSizes[0]) * event_specid->numberOfAlgorithms + sizeof(*vendor) + vendor->vendorInfoSize) { LOG_ERR("insufficient size for VendorStuff data"); return false; } *next = (TCG_EVENT_HEADER2*)((uintptr_t)vendor->vendorInfo + vendor->vendorInfoSize); return true; } bool parse_eventlog(tpm2_eventlog_context *ctx, BYTE const *eventlog, size_t size) { if(!eventlog) { return false; } if(size < sizeof(TCG_EVENT)) { return false; } TCG_EVENT *event = (TCG_EVENT*)eventlog; if (event->eventType == EV_NO_ACTION) { TCG_EVENT_HEADER2 *next; bool ret = specid_event(event, size, &next); if (!ret) { return false; } size -= (uintptr_t)next - (uintptr_t)eventlog; if (ctx->specid_cb) { ret = ctx->specid_cb(event, ctx->data); if (!ret) { return false; } } return foreach_event2(ctx, next, size); } /* No specid event found. sha1 log format will be parsed. */ return foreach_sha1_log_event(ctx, event, size); } tpm2-tools-5.2/lib/tpm2_eventlog.h000066400000000000000000000042761412464516500171250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TPM2_EVENTLOG_H #define TPM2_EVENTLOG_H #include #include #include #include "efi_event.h" typedef bool (*DIGEST2_CALLBACK)(TCG_DIGEST2 const *digest, size_t size, void *data); typedef bool (*EVENT2_CALLBACK)(TCG_EVENT_HEADER2 const *event_hdr, size_t size, void *data); typedef bool (*EVENT2DATA_CALLBACK)(TCG_EVENT2 const *event, UINT32 type, void *data, uint32_t eventlog_version); typedef bool (*SPECID_CALLBACK)(TCG_EVENT const *event, void *data); typedef bool (*LOG_EVENT_CALLBACK)(TCG_EVENT const *event_hdr, size_t size, void *data); typedef struct { void *data; SPECID_CALLBACK specid_cb; LOG_EVENT_CALLBACK log_eventhdr_cb; EVENT2_CALLBACK event2hdr_cb; DIGEST2_CALLBACK digest2_cb; EVENT2DATA_CALLBACK event2_cb; uint32_t sha1_used; uint32_t sha256_used; uint32_t sha384_used; uint32_t sha512_used; uint32_t sm3_256_used; uint8_t sha1_pcrs[TPM2_MAX_PCRS][TPM2_SHA1_DIGEST_SIZE]; uint8_t sha256_pcrs[TPM2_MAX_PCRS][TPM2_SHA256_DIGEST_SIZE]; uint8_t sha384_pcrs[TPM2_MAX_PCRS][TPM2_SHA384_DIGEST_SIZE]; uint8_t sha512_pcrs[TPM2_MAX_PCRS][TPM2_SHA512_DIGEST_SIZE]; uint8_t sm3_256_pcrs[TPM2_MAX_PCRS][TPM2_SM3_256_DIGEST_SIZE]; uint32_t eventlog_version; } tpm2_eventlog_context; bool digest2_accumulator_callback(TCG_DIGEST2 const *digest, size_t size, void *data); bool parse_event2body(TCG_EVENT2 const *event, UINT32 type); bool foreach_digest2(tpm2_eventlog_context *ctx, unsigned pcr_index, TCG_DIGEST2 const *event_hdr, size_t count, size_t size); bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size, size_t *event_size, size_t *digests_size); bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhdr_start, size_t size); bool specid_event(TCG_EVENT const *event, size_t size, TCG_EVENT_HEADER2 **next); bool parse_eventlog(tpm2_eventlog_context *ctx, BYTE const *eventlog, size_t size); #endif tpm2-tools-5.2/lib/tpm2_eventlog_yaml.c000066400000000000000000001070031412464516500201320ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "log.h" #include "efi_event.h" #include "tpm2_alg_util.h" #include "tpm2_eventlog.h" #include "tpm2_eventlog_yaml.h" #include "tpm2_tool.h" #include "tpm2_tool_output.h" #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_EFIVAR_EFIVAR_H #include #endif static void guid_unparse_lower(EFI_GUID guid, char guid_buf[37]) { snprintf(guid_buf, 37, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); } char const *eventtype_to_string (UINT32 event_type) { switch (event_type) { case EV_PREBOOT_CERT: return "EV_PREBOOT_CERT"; case EV_POST_CODE: return "EV_POST_CODE"; case EV_UNUSED: return "EV_UNUSED"; case EV_NO_ACTION: return "EV_NO_ACTION"; case EV_SEPARATOR: return "EV_SEPARATOR"; case EV_ACTION: return "EV_ACTION"; case EV_EVENT_TAG: return "EV_EVENT_TAG"; case EV_S_CRTM_CONTENTS: return "EV_S_CRTM_CONTENTS"; case EV_S_CRTM_VERSION: return "EV_S_CRTM_VERSION"; case EV_CPU_MICROCODE: return "EV_CPU_MICROCODE"; case EV_PLATFORM_CONFIG_FLAGS: return "EV_PLATFORM_CONFIG_FLAGS"; case EV_TABLE_OF_DEVICES: return "EV_TABLE_OF_DEVICES"; case EV_COMPACT_HASH: return "EV_COMPACT_HASH"; case EV_IPL: return "EV_IPL"; case EV_IPL_PARTITION_DATA: return "EV_IPL_PARTITION_DATA"; case EV_NONHOST_CODE: return "EV_NONHOST_CODE"; case EV_NONHOST_CONFIG: return "EV_NONHOST_CONFIG"; case EV_NONHOST_INFO: return "EV_NONHOST_INFO"; case EV_OMIT_BOOT_DEVICE_EVENTS: return "EV_OMIT_BOOT_DEVICE_EVENTS"; case EV_EFI_VARIABLE_DRIVER_CONFIG: return "EV_EFI_VARIABLE_DRIVER_CONFIG"; case EV_EFI_VARIABLE_BOOT: return "EV_EFI_VARIABLE_BOOT"; case EV_EFI_BOOT_SERVICES_APPLICATION: return "EV_EFI_BOOT_SERVICES_APPLICATION"; case EV_EFI_BOOT_SERVICES_DRIVER: return "EV_EFI_BOOT_SERVICES_DRIVER"; case EV_EFI_RUNTIME_SERVICES_DRIVER: return "EV_EFI_RUNTIME_SERVICES_DRIVER"; case EV_EFI_GPT_EVENT: return "EV_EFI_GPT_EVENT"; case EV_EFI_ACTION: return "EV_EFI_ACTION"; case EV_EFI_PLATFORM_FIRMWARE_BLOB: return "EV_EFI_PLATFORM_FIRMWARE_BLOB"; case EV_EFI_HANDOFF_TABLES: return "EV_EFI_HANDOFF_TABLES"; case EV_EFI_VARIABLE_AUTHORITY: return "EV_EFI_VARIABLE_AUTHORITY"; default: return "Unknown event type"; } } void bytes_to_str(uint8_t const *buf, size_t size, char *dest, size_t dest_size) { size_t i, j; for(i = 0, j = 0; i < size && j < dest_size - 2; ++i, j+=2) { sprintf(&dest[j], "%02x", buf[i]); } dest[j] = '\0'; } void yaml_event2hdr(TCG_EVENT_HEADER2 const *eventhdr, size_t size) { (void)size; tpm2_tool_output(" PCRIndex: %d\n" " EventType: %s\n" " DigestCount: %d\n", eventhdr->PCRIndex, eventtype_to_string(eventhdr->EventType), eventhdr->DigestCount); return; } void yaml_sha1_log_eventhdr(TCG_EVENT const *eventhdr, size_t size) { (void)size; tpm2_tool_output(" PCRIndex: %d\n" " EventType: %s\n", eventhdr->pcrIndex, eventtype_to_string(eventhdr->eventType)); return; } /* converting byte buffer to hex string requires 2x, plus 1 for '\0' */ #define BYTES_TO_HEX_STRING_SIZE(byte_count) ((byte_count) * 2 + 1) #define DIGEST_HEX_STRING_MAX BYTES_TO_HEX_STRING_SIZE(TPM2_MAX_DIGEST_BUFFER) bool yaml_digest2(TCG_DIGEST2 const *digest, size_t size) { char hexstr[DIGEST_HEX_STRING_MAX] = { 0, }; bytes_to_str(digest->Digest, size, hexstr, sizeof(hexstr)); tpm2_tool_output(" - AlgorithmId: %s\n" " Digest: \"%s\"\n", tpm2_alg_util_algtostr(digest->AlgorithmId, tpm2_alg_util_flags_hash), hexstr); return true; } static char *yaml_utf16_to_str(UTF16_CHAR *data, size_t len) { int ret = 0; mbstate_t st; memset(&st, '\0', sizeof(st)); char *mbstr = calloc(len + 1, MB_CUR_MAX); char *tmp = mbstr; if (mbstr == NULL) { LOG_ERR("failed to allocate data: %s\n", strerror(errno)); return NULL; } for(size_t i = 0; i < len; ++i, tmp += ret) { ret = c16rtomb(tmp, data[i].c, &st); if (ret < 0) { LOG_ERR("c16rtomb failed: %s", strerror(errno)); free(mbstr); return NULL; } } return mbstr; } #define VAR_DATA_HEX_SIZE(data) BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength) static bool yaml_uefi_var_data(UEFI_VARIABLE_DATA *data) { if (data->VariableDataLength == 0) { return true; } char *var_data = calloc (1, VAR_DATA_HEX_SIZE(data)); uint8_t *variable_data = (uint8_t*)&data->UnicodeName[ data->UnicodeNameLength]; if (var_data == NULL) { LOG_ERR("failled to allocate data: %s\n", strerror(errno)); return false; } bytes_to_str(variable_data, data->VariableDataLength, var_data, VAR_DATA_HEX_SIZE(data)); tpm2_tool_output(" VariableData: \"%s\"\n", var_data); free(var_data); return true; } /* * TCG PC Client FPF section 2.3.4.1 and 9.4.1: * Usage of the event type EV_POST_CODE: * - If a combined event is measured, the event field SHOULD * be the string "POST CODE" in all caps. ... * - Embedded SMM code and the code that sets it up SHOULD use * the string "SMM CODE" in all caps... * - BIS code (excluding the BIS Certificate) should use event * field string of "BIS CODE" in all caps. ... * - ACPI flash data prior to any modifications ... should use * event field string of "ACPI DATA" in all caps. * * Section 9.2.5 also says "...Below is the definition of the * UEFI_PLATFORM_FIRMWARE_BLOB structure that the CRTM MUST put * into the Event Log entry TCG_PCR_EVENT2.event[1] field for * event types EV_POST_CODE, EV_S_CRTM_CONTENTS, and * EV_EFI_PLATFORM_FIRMWARE_BLOB." */ static bool yaml_uefi_post_code(const TCG_EVENT2* const event) { const size_t len = event->EventSize; /* if length is 16, we treat it as EV_EFI_PLATFORM_FIRMWARE_BLOB */ if (len == 16) { const UEFI_PLATFORM_FIRMWARE_BLOB * const blob = \ (const UEFI_PLATFORM_FIRMWARE_BLOB*) event->Event; tpm2_tool_output(" Event:\n" " BlobBase: 0x%" PRIx64 "\n" " BlobLength: 0x%" PRIx64 "\n", blob->BlobBase, blob->BlobLength); } else { // otherwise, we treat it as an ASCII string const char* const data = (const char *) event->Event; tpm2_tool_output(" Event: |-\n" " %.*s\n", (int) len, data); } return true; } /* * Parses Device Path field using the efivar library if present, otherwise, * print the field in raw byte format */ #ifdef HAVE_EFIVAR_EFIVAR_H char *yaml_devicepath(BYTE* dp, UINT64 dp_len) { int ret; ret = efidp_format_device_path(NULL, 0, (const_efidp)dp, dp_len); if (ret < 0) { LOG_ERR("failed to allocate memory: %s\n", strerror(errno)); return NULL; } int text_path_len; char *text_path; text_path_len = ret + 1; text_path = (char*)malloc(text_path_len); if (!text_path) { LOG_ERR("failed to allocate memory: %s\n", strerror(errno)); return NULL; } ret = efidp_format_device_path(text_path, text_path_len, (const_efidp)dp, dp_len); if (ret < 0) { free(text_path); LOG_ERR("cannot parse device path\n"); return NULL; } return text_path; } #endif /* * TCG PC Client FPF section 9.2.6 * The tpm2_eventlog module validates the event structure but nothing within * the event data buffer so we must do that here. */ static bool yaml_uefi_var(UEFI_VARIABLE_DATA *data, size_t size, UINT32 type, uint32_t eventlog_version) { char uuidstr[37] = { 0 }; size_t start = 0; if (size < sizeof(*data)) { LOG_ERR("EventSize is too small\n"); return false; } guid_unparse_lower(data->VariableName, uuidstr); tpm2_tool_output(" Event:\n" " VariableName: %s\n" " UnicodeNameLength: %"PRIu64"\n" " VariableDataLength: %" PRIu64 "\n", uuidstr, data->UnicodeNameLength, data->VariableDataLength); start += sizeof(*data); if (start + data->UnicodeNameLength*2 > size) { LOG_ERR("EventSize is too small\n"); return false; } char *ret = yaml_utf16_to_str(data->UnicodeName, data->UnicodeNameLength); if (!ret) { return false; } tpm2_tool_output(" UnicodeName: %s\n", ret); start += data->UnicodeNameLength*2; /* Try to parse as much as we can without fail-stop. Bugs in firmware, shim, * grub could produce inconsistent metadata. As long as it is not preventing * us from parsing the data, we try to continue while giving a warning * message. */ if (start + data->VariableDataLength > size) { LOG_ERR("EventSize is inconsistent with actual data\n"); } if (eventlog_version == 2) { /* PK, KEK, db, and dbx are reserved variables names used to store platform * keys, key exchange keys, database keys, and blacklisted database keys, * respectively. */ if (type == EV_EFI_VARIABLE_DRIVER_CONFIG) { if ((strlen(ret) == 2 && strncmp(ret, "PK", 2) == 0) || (strlen(ret) == 3 && strncmp(ret, "KEK", 3) == 0) || (strlen(ret) == 2 && strncmp(ret, "db", 2) == 0) || (strlen(ret) == 3 && strncmp(ret, "dbx", 3) == 0)) { free(ret); tpm2_tool_output(" VariableData:\n"); uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ data->UnicodeNameLength]; /* iterate through each EFI_SIGNATURE_LIST */ while (start < size) { EFI_SIGNATURE_LIST *slist = (EFI_SIGNATURE_LIST *)variable_data; if (start + sizeof(*slist) > size) { LOG_ERR("EventSize is inconsistent with actual data\n"); break; } if (slist->SignatureSize < 16) { LOG_ERR("SignatureSize is too small\n"); break; } guid_unparse_lower(slist->SignatureType, uuidstr); tpm2_tool_output(" - SignatureType: %s\n" " SignatureListSize: %" PRIu32 "\n" " SignatureHeaderSize: %" PRIu32 "\n" " SignatureSize: %" PRIu32 "\n" " Keys:\n", uuidstr, slist->SignatureListSize, slist->SignatureHeaderSize, slist->SignatureSize); start += (sizeof(*slist) + slist->SignatureHeaderSize); if (start + slist->SignatureSize > size) { LOG_ERR("EventSize is inconsistent with actual data\n"); break; } int signature_size = slist->SignatureListSize - sizeof(*slist) - slist->SignatureHeaderSize; if (signature_size < 0 || signature_size % slist->SignatureSize != 0) { LOG_ERR("Malformed EFI_SIGNATURE_LIST\n"); break; } uint8_t *signature = (uint8_t *)slist + sizeof(*slist) + slist->SignatureHeaderSize; int signatures = signature_size / slist->SignatureSize; /* iterate through each EFI_SIGNATURE on the list */ int i; for (i = 0; i < signatures; i++) { EFI_SIGNATURE_DATA *s = (EFI_SIGNATURE_DATA *)signature; char *sdata = calloc (1, BYTES_TO_HEX_STRING_SIZE(slist->SignatureSize-16)); if (sdata == NULL) { LOG_ERR("Failled to allocate data: %s\n", strerror(errno)); return false; } bytes_to_str(s->SignatureData, slist->SignatureSize-16, sdata, BYTES_TO_HEX_STRING_SIZE(slist->SignatureSize-16)); guid_unparse_lower(s->SignatureOwner, uuidstr); tpm2_tool_output(" - SignatureOwner: %s\n" " SignatureData: %s\n", uuidstr, sdata); free(sdata); signature += slist->SignatureSize; start += slist->SignatureSize; if (start > size) { LOG_ERR("Malformed EFI_SIGNATURE_DATA\n"); break; } } variable_data += slist->SignatureListSize; } return true; } else if ((strlen(ret) == 10 && strncmp(ret, "SecureBoot", 10) == 0)) { free(ret); tpm2_tool_output(" VariableData:\n" " Enabled: "); if (data->VariableDataLength == 0) { tpm2_tool_output("'No'\n"); } else if (data->VariableDataLength > 1) { LOG_ERR("SecureBoot value length %" PRIu64 " is unexpectedly > 1\n", data->VariableDataLength); return false; } else { uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ data->UnicodeNameLength]; if (*variable_data == 0) { tpm2_tool_output("'No'\n"); } else { tpm2_tool_output("'Yes'\n"); } } return true; } /* Other variables will be printed as a hex string */ } else if (type == EV_EFI_VARIABLE_AUTHORITY) { free(ret); tpm2_tool_output(" VariableData:\n"); EFI_SIGNATURE_DATA *s= (EFI_SIGNATURE_DATA *)&data->UnicodeName[ data->UnicodeNameLength]; char *sdata = calloc (1, BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength - 16)); if (sdata == NULL) { LOG_ERR("Failled to allocate data: %s\n", strerror(errno)); return false; } bytes_to_str(s->SignatureData, data->VariableDataLength - 16, sdata, BYTES_TO_HEX_STRING_SIZE(data->VariableDataLength - 16)); guid_unparse_lower(s->SignatureOwner, uuidstr); tpm2_tool_output(" - SignatureOwner: %s\n" " SignatureData: %s\n", uuidstr, sdata); free(sdata); return true; } else if (type == EV_EFI_VARIABLE_BOOT) { if ((strlen(ret) == 9 && strncmp(ret, "BootOrder", 9) == 0)) { free(ret); tpm2_tool_output(" VariableData:\n"); if (data->VariableDataLength % 2 != 0) { LOG_ERR("BootOrder value length %" PRIu64 " is not divisible by 2\n", data->VariableDataLength); return false; } uint8_t *variable_data = (uint8_t *)&data->UnicodeName[ data->UnicodeNameLength]; for (uint64_t i = 0; i < data->VariableDataLength / 2; i++) { tpm2_tool_output(" - Boot%04x\n", *((uint16_t*)variable_data + i)); } return true; } /* Test for regex "^Boot[0-9a-fA-F]\\{4\\}$" */ if (strlen(ret) == 8 && strncmp(ret, "Boot", 4) == 0 && isxdigit((int)ret[4]) && isxdigit((int)ret[5]) && isxdigit((int)ret[6]) && isxdigit((int)ret[7])) { free(ret); tpm2_tool_output(" VariableData:\n" " Enabled: "); EFI_LOAD_OPTION *loadopt = (EFI_LOAD_OPTION*)&data->UnicodeName[ data->UnicodeNameLength]; if (loadopt->Attributes & 1) { tpm2_tool_output("'Yes'\n"); } else { tpm2_tool_output("'No'\n"); } tpm2_tool_output(" FilePathListLength: %" PRIu16 "\n", loadopt->FilePathListLength); tpm2_tool_output(" Description: \""); int i; for (i = 0; (wchar_t)loadopt->Description[i] != 0; i++) { wchar_t c = (wchar_t)loadopt->Description[i]; tpm2_tool_output("%lc", c); } tpm2_tool_output("\"\n"); uint8_t *devpath = (uint8_t*)&loadopt->Description[++i]; size_t devpath_len = (data->VariableDataLength - sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i) * 2 + 1; char *buf = calloc(1, devpath_len); if (!buf) { LOG_ERR("failed to allocate memory: %s\n", strerror(errno)); return false; } #ifdef HAVE_EFIVAR_EFIVAR_H char *dp = yaml_devicepath(devpath, devpath_len); if (dp) { tpm2_tool_output(" DevicePath: '%s'\n", dp); free(dp); } else { /* fallback to printing the raw bytes if devicepath cannot be parsed */ bytes_to_str(devpath, data->VariableDataLength - sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i, buf, devpath_len); tpm2_tool_output(" DevicePath: '%s'\n", buf); } #else bytes_to_str(devpath, data->VariableDataLength - sizeof(EFI_LOAD_OPTION) - sizeof(UINT16) * i, buf, devpath_len); tpm2_tool_output(" DevicePath: '%s'\n", buf); #endif free(buf); return true; } } /* Other event types will be printed as a hex string */ } free(ret); return yaml_uefi_var_data(data); } /* TCG PC Client FPF section 9.2.5 */ bool yaml_uefi_platfwblob(UEFI_PLATFORM_FIRMWARE_BLOB *data) { tpm2_tool_output(" Event:\n" " BlobBase: 0x%" PRIx64 "\n" " BlobLength: 0x%" PRIx64 "\n", data->BlobBase, data->BlobLength); return true; } /* TCG PC Client PFP section 9.4.4 */ bool yaml_uefi_action(UINT8 const *action, size_t size) { tpm2_tool_output(" Event: |-\n" " %.*s\n", (int) size, action); return true; } /* * TCG PC Client PFP section 9.4.1 * This event type is extensively used by the Shim and Grub on a wide varities * of Linux distributions to measure grub and kernel command line parameters and * the loading of grub, kernel, and initrd images. */ bool yaml_ipl(UINT8 const *description, size_t size) { tpm2_tool_output(" Event:\n" " String: |-\n"); /* We need to handle when description contains multiple lines. */ size_t i, j; for (i = 0; i < size; i++) { for (j = i; j < size; j++) { if (description[j] == '\n' || description[j] == '\0') { break; } } tpm2_tool_output(" %.*s\n", (int)(j - i), description+i); i = j; } return true; } /* TCG PC Client PFP section 9.2.3 */ bool yaml_uefi_image_load(UEFI_IMAGE_LOAD_EVENT *data, size_t size) { size_t devpath_len = (size - sizeof(*data)) * 2 + 1; char *buf = calloc(1, devpath_len); if (!buf) { LOG_ERR("failed to allocate memory: %s\n", strerror(errno)); return false; } tpm2_tool_output(" Event:\n" " ImageLocationInMemory: 0x%" PRIx64 "\n" " ImageLengthInMemory: %" PRIu64 "\n" " ImageLinkTimeAddress: 0x%" PRIx64 "\n" " LengthOfDevicePath: %" PRIu64 "\n", data->ImageLocationInMemory, data->ImageLengthInMemory, data->ImageLinkTimeAddress, data->LengthOfDevicePath); #ifdef HAVE_EFIVAR_EFIVAR_H char *dp = yaml_devicepath(data->DevicePath, data->LengthOfDevicePath); if (dp) { tpm2_tool_output(" DevicePath: '%s'\n", dp); free(dp); } else { /* fallback to printing the raw bytes if devicepath cannot be parsed */ bytes_to_str(data->DevicePath, size - sizeof(*data), buf, devpath_len); tpm2_tool_output(" DevicePath: '%s'\n", buf); } #else bytes_to_str(data->DevicePath, size - sizeof(*data), buf, devpath_len); tpm2_tool_output(" DevicePath: '%s'\n", buf); #endif free(buf); return true; } #define EVENT_BUF_MAX BYTES_TO_HEX_STRING_SIZE(1024) /* TCG PC Client PFP section 9.2.6 */ bool yaml_gpt(UEFI_GPT_DATA *data, size_t size, uint32_t eventlog_version) { if (size < sizeof(*data)) { LOG_ERR("EventSize(%zu) is too small\n", size); return false; } if (eventlog_version == 2) { UEFI_PARTITION_TABLE_HEADER *header = &data->UEFIPartitionHeader; char guid[37] = { 0 }; guid_unparse_lower(header->DiskGUID, guid); tpm2_tool_output(" Event:\n" " Header:\n" " Signature: \"%.*s\"\n" " Revision: 0x%" PRIx32 "\n" " HeaderSize: %" PRIu32 "\n" " HeaderCRC32: 0x%" PRIx32 "\n" " MyLBA: 0x%" PRIx64 "\n" " AlternateLBA: 0x%" PRIx64 "\n" " FirstUsableLBA: 0x%" PRIx64 "\n" " LastUsableLBA: 0x%" PRIx64 "\n" " DiskGUID: %s\n" " PartitionEntryLBA: 0x%" PRIx64 "\n" " NumberOfPartitionEntry: %" PRIu32 "\n" " SizeOfPartitionEntry: %" PRIu32 "\n" " PartitionEntryArrayCRC32: 0x%" PRIx32 "\n" " NumberOfPartitions: %" PRIu64 "\n" " Partitions:\n", 8, (char*)&header->Signature, /* 8-char ASCII string */ header->Revision, header->HeaderSize, header->HeaderCRC32, header->MyLBA, header->AlternateLBA, header->FirstUsableLBA, header->LastUsableLBA, guid, header->PartitionEntryLBA, header->NumberOfPartitionEntries, header->SizeOfPartitionEntry, header->PartitionEntryArrayCRC32, data->NumberOfPartitions); size -= (sizeof(data->UEFIPartitionHeader) + sizeof(data->NumberOfPartitions)); UINT64 i; for (i = 0; i < data->NumberOfPartitions; i++) { UEFI_PARTITION_ENTRY *partition = &data->Partitions[i]; if (size < sizeof(*partition)) { LOG_ERR("Cannot parse GPT partition entry: insufficient data (%zu)\n", size); return false; } guid_unparse_lower(partition->PartitionTypeGUID, guid); tpm2_tool_output(" - PartitionTypeGUID: %s\n", guid); guid_unparse_lower(partition->UniquePartitionGUID, guid); size_t len = sizeof(partition->PartitionName) / sizeof(UTF16_CHAR); char *part_name = yaml_utf16_to_str(partition->PartitionName, len); tpm2_tool_output(" UniquePartitionGUID: %s\n" " StartingLBA: 0x%" PRIx64 "\n" " EndingLBA: 0x%" PRIx64 "\n" " Attributes: 0x%" PRIx64 "\n" " PartitionName: \"%s\"\n", guid, partition->StartingLBA, partition->EndingLBA, partition->Attributes, part_name); free(part_name); size -= sizeof(*partition); } if (size != 0) { LOG_ERR("EventSize is inconsistent with actual data\n"); return false; } } else { char hexstr[EVENT_BUF_MAX] = { 0, }; bytes_to_str((UINT8*)data, size, hexstr, sizeof(hexstr)); tpm2_tool_output(" Event: \"%s\"\n", hexstr); } return true; } /* TCG PC Client PFP section 9.2.6 */ bool yaml_no_action(EV_NO_ACTION_STRUCT *data, size_t size, uint32_t eventlog_version) { if (eventlog_version == 2) { if (size > sizeof(STARTUP_LOCALITY_SIGNATURE) && memcmp(data->Signature, STARTUP_LOCALITY_SIGNATURE, sizeof(STARTUP_LOCALITY_SIGNATURE)) == 0) { tpm2_tool_output(" Event:\n" " StartupLocality: %u\n", data->Cases.StartupLocality); return true; } } char hexstr[EVENT_BUF_MAX] = { 0, }; bytes_to_str((UINT8*)data, size, hexstr, sizeof(hexstr)); tpm2_tool_output(" Event: \"%s\"\n", hexstr); return true; } bool yaml_event2data(TCG_EVENT2 const *event, UINT32 type, uint32_t eventlog_version) { char hexstr[EVENT_BUF_MAX] = { 0, }; tpm2_tool_output(" EventSize: %" PRIu32 "\n", event->EventSize); if (event->EventSize == 0) { return true; } switch (type) { case EV_EFI_VARIABLE_DRIVER_CONFIG: case EV_EFI_VARIABLE_BOOT: case EV_EFI_VARIABLE_AUTHORITY: return yaml_uefi_var((UEFI_VARIABLE_DATA*)event->Event, event->EventSize, type, eventlog_version); case EV_POST_CODE: return yaml_uefi_post_code(event); case EV_S_CRTM_CONTENTS: case EV_EFI_PLATFORM_FIRMWARE_BLOB: return yaml_uefi_platfwblob((UEFI_PLATFORM_FIRMWARE_BLOB*)event->Event); case EV_EFI_ACTION: return yaml_uefi_action(event->Event, event->EventSize); case EV_IPL: return yaml_ipl(event->Event, event->EventSize); case EV_EFI_BOOT_SERVICES_APPLICATION: case EV_EFI_BOOT_SERVICES_DRIVER: case EV_EFI_RUNTIME_SERVICES_DRIVER: return yaml_uefi_image_load((UEFI_IMAGE_LOAD_EVENT*)event->Event, event->EventSize); case EV_EFI_GPT_EVENT: return yaml_gpt((UEFI_GPT_DATA*)event->Event, event->EventSize, eventlog_version); case EV_NO_ACTION: return yaml_no_action((EV_NO_ACTION_STRUCT*)event->Event, event->EventSize, eventlog_version); default: bytes_to_str(event->Event, event->EventSize, hexstr, sizeof(hexstr)); tpm2_tool_output(" Event: \"%s\"\n", hexstr); return true; } } bool yaml_event2data_callback(TCG_EVENT2 const *event, UINT32 type, void *data, uint32_t eventlog_version) { (void)data; return yaml_event2data(event, type, eventlog_version); } bool yaml_digest2_callback(TCG_DIGEST2 const *digest, size_t size, void *data_in) { (void)data_in; return yaml_digest2(digest, size); } bool yaml_event2hdr_callback(TCG_EVENT_HEADER2 const *eventhdr, size_t size, void *data_in) { size_t *count = (size_t*)data_in; if (count == NULL) { LOG_ERR("callback requires user data"); return false; } tpm2_tool_output("- EventNum: %zu\n", (*count)++); yaml_event2hdr(eventhdr, size); tpm2_tool_output(" Digests:\n"); return true; } bool yaml_sha1_log_eventhdr_callback(TCG_EVENT const *eventhdr, size_t size, void *data_in) { (void)data_in; yaml_sha1_log_eventhdr(eventhdr, size); char hexstr[BYTES_TO_HEX_STRING_SIZE(sizeof(eventhdr->digest))] = { 0, }; bytes_to_str(eventhdr->digest, sizeof(eventhdr->digest), hexstr, sizeof(hexstr)); tpm2_tool_output(" DigestCount: 1\n" " Digests:\n" " - AlgorithmId: %s\n" " Digest: \"%s\"\n", tpm2_alg_util_algtostr(TPM2_ALG_SHA1, tpm2_alg_util_flags_hash), hexstr); return true; } void yaml_eventhdr(TCG_EVENT const *event, size_t *count) { /* digest is 20 bytes, 2 chars / byte and null terminator for string*/ char digest_hex[2*sizeof(event->digest) + 1] = {}; bytes_to_str(event->digest, sizeof(event->digest), digest_hex, sizeof(digest_hex)); tpm2_tool_output("- EventNum: %zu\n" " PCRIndex: %" PRIu32 "\n" " EventType: %s\n" " Digest: \"%s\"\n" " EventSize: %" PRIu32 "\n", (*count)++, event->pcrIndex, eventtype_to_string(event->eventType), digest_hex, event->eventDataSize); } void yaml_specid(TCG_SPECID_EVENT* specid) { /* 'Signature' defined as byte buf, spec treats it like string w/o null. */ char sig_str[sizeof(specid->Signature) + 1] = { '\0', }; memcpy(sig_str, specid->Signature, sizeof(specid->Signature)); tpm2_tool_output(" SpecID:\n" " - Signature: %s\n" " platformClass: %" PRIu32 "\n" " specVersionMinor: %" PRIu8 "\n" " specVersionMajor: %" PRIu8 "\n" " specErrata: %" PRIu8 "\n" " uintnSize: %" PRIu8 "\n" " numberOfAlgorithms: %" PRIu32 "\n" " Algorithms:\n", sig_str, specid->platformClass, specid->specVersionMinor, specid->specVersionMajor, specid->specErrata, specid->uintnSize, specid->numberOfAlgorithms); } void yaml_specid_algs(TCG_SPECID_ALG const *alg, size_t count) { for (size_t i = 0; i < count; ++i, ++alg) { tpm2_tool_output(" - Algorithm[%zu]:\n" " algorithmId: %s\n" " digestSize: %" PRIu16 "\n", i, tpm2_alg_util_algtostr(alg->algorithmId, tpm2_alg_util_flags_hash), alg->digestSize); } } bool yaml_specid_vendor(TCG_VENDOR_INFO *vendor) { char *vendinfo_str; tpm2_tool_output(" vendorInfoSize: %" PRIu8 "\n", vendor->vendorInfoSize); if (vendor->vendorInfoSize == 0) { return true; } vendinfo_str = calloc(1, vendor->vendorInfoSize * 2 + 1); if (vendinfo_str == NULL) { LOG_ERR("failed to allocate memory for vendorInfo: %s\n", strerror(errno)); return false; } bytes_to_str(vendor->vendorInfo, vendor->vendorInfoSize, vendinfo_str, vendor->vendorInfoSize * 2 + 1); tpm2_tool_output(" vendorInfo: \"%s\"\n", vendinfo_str); free(vendinfo_str); return true; } bool yaml_specid_event(TCG_EVENT const *event, size_t *count) { TCG_SPECID_EVENT *specid = (TCG_SPECID_EVENT*)event->event; TCG_SPECID_ALG *alg = (TCG_SPECID_ALG*)specid->digestSizes; TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)(alg + specid->numberOfAlgorithms); yaml_eventhdr(event, count); yaml_specid(specid); yaml_specid_algs(alg, specid->numberOfAlgorithms); return yaml_specid_vendor(vendor); } bool yaml_specid_callback(TCG_EVENT const *event, void *data) { size_t *count = (size_t*)data; return yaml_specid_event(event, count); } static void yaml_eventlog_pcrs(tpm2_eventlog_context *ctx) { char hexstr[DIGEST_HEX_STRING_MAX] = { 0, }; tpm2_tool_output("pcrs:\n"); if (ctx->sha1_used != 0) { tpm2_tool_output(" sha1:\n"); for(unsigned i = 0 ; i < TPM2_MAX_PCRS ; i++) { if ((ctx->sha1_used & (1 << i)) == 0) continue; bytes_to_str(ctx->sha1_pcrs[i], sizeof(ctx->sha1_pcrs[i]), hexstr, sizeof(hexstr)); tpm2_tool_output(" %-2d : 0x%s\n", i, hexstr); } } if (ctx->sha256_used != 0) { tpm2_tool_output(" sha256:\n"); for(unsigned i = 0 ; i < TPM2_MAX_PCRS ; i++) { if ((ctx->sha256_used & (1 << i)) == 0) continue; bytes_to_str(ctx->sha256_pcrs[i], sizeof(ctx->sha256_pcrs[i]), hexstr, sizeof(hexstr)); tpm2_tool_output(" %-2d : 0x%s\n", i, hexstr); } } if (ctx->sha384_used != 0) { tpm2_tool_output(" sha384:\n"); for(unsigned i = 0 ; i < TPM2_MAX_PCRS ; i++) { if ((ctx->sha384_used & (1 << i)) == 0) continue; bytes_to_str(ctx->sha384_pcrs[i], sizeof(ctx->sha384_pcrs[i]), hexstr, sizeof(hexstr)); tpm2_tool_output(" %-2d : 0x%s\n", i, hexstr); } } if (ctx->sha512_used != 0) { tpm2_tool_output(" sha512:\n"); for(unsigned i = 0 ; i < TPM2_MAX_PCRS ; i++) { if ((ctx->sha512_used & (1 << i)) == 0) continue; bytes_to_str(ctx->sha512_pcrs[i], sizeof(ctx->sha512_pcrs[i]), hexstr, sizeof(hexstr)); tpm2_tool_output(" %-2d : 0x%s\n", i, hexstr); } } if (ctx->sm3_256_used != 0) { tpm2_tool_output(" sm3_256:\n"); for(unsigned i = 0 ; i < TPM2_MAX_PCRS ; i++) { if ((ctx->sm3_256_used & (1 << i)) == 0) continue; bytes_to_str(ctx->sm3_256_pcrs[i], sizeof(ctx->sm3_256_pcrs[i]), hexstr, sizeof(hexstr)); tpm2_tool_output(" %-2d : 0x%s\n", i, hexstr); } } } bool yaml_eventlog(UINT8 const *eventlog, size_t size, uint32_t eventlog_version) { if (eventlog_version < MIN_EVLOG_YAML_VERSION || eventlog_version > MAX_EVLOG_YAML_VERSION) { LOG_ERR("Unexpected YAML version number: %u\n", eventlog_version); return false; } size_t count = 0; tpm2_eventlog_context ctx = { .data = &count, .specid_cb = yaml_specid_callback, .event2hdr_cb = yaml_event2hdr_callback, .log_eventhdr_cb = yaml_sha1_log_eventhdr_callback, .digest2_cb = yaml_digest2_callback, .event2_cb = yaml_event2data_callback, .eventlog_version = eventlog_version, }; tpm2_tool_output("---\n"); tpm2_tool_output("version: %u\n", eventlog_version); tpm2_tool_output("events:\n"); bool rc = parse_eventlog(&ctx, eventlog, size); if (!rc) { return rc; } yaml_eventlog_pcrs(&ctx); return true; } tpm2-tools-5.2/lib/tpm2_eventlog_yaml.h000066400000000000000000000017021412464516500201360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TPM2_EVENTLOG_YAML_H #define TPM2_EVENTLOG_YAML_H #include #include #include "efi_event.h" #include "tpm2_eventlog.h" #define MIN_EVLOG_YAML_VERSION 1 #define MAX_EVLOG_YAML_VERSION 2 char const *eventtype_to_string (UINT32 event_type); void yaml_event2hdr(TCG_EVENT_HEADER2 const *event_hdr, size_t size); bool yaml_digest2(TCG_DIGEST2 const *digest, size_t size); bool yaml_event2data(TCG_EVENT2 const *event, UINT32 type, uint32_t eventlog_version); bool yaml_digest2_callback(TCG_DIGEST2 const *digest, size_t size, void *data); bool yaml_event2hdr_callback(TCG_EVENT_HEADER2 const *event_hdr, size_t size, void *data); bool yaml_event2data_callback(TCG_EVENT2 const *event, UINT32 type, void *data, uint32_t eventlog_version); bool yaml_eventlog(UINT8 const *eventlog, size_t size, uint32_t eventlog_version); #endif tpm2-tools-5.2/lib/tpm2_hash.c000066400000000000000000000104751412464516500162160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_hash.h" static tool_rc tpm2_hash_common(ESYS_CONTEXT *ectx, TPMI_ALG_HASH halg, TPMI_RH_HIERARCHY hierarchy, FILE *infilep, BYTE *inbuffer, UINT16 inbuffer_len, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { bool use_left = true, done; unsigned long left = inbuffer_len; size_t bytes_read; TPM2B_AUTH null_auth = TPM2B_EMPTY_INIT; TPMI_DH_OBJECT sequence_handle; TPM2B_MAX_BUFFER buffer; /* if we're using infilep, get file size */ if (!!infilep) { /* Suppress error reporting with NULL path */ use_left = files_get_file_size(infilep, &left, NULL); } /* if data length is non-zero (valid) and less than 1024, just do it in one hash invocation */ if (use_left && left <= TPM2_MAX_DIGEST_BUFFER) { buffer.size = left; if (!!infilep) { bool res = files_read_bytes(infilep, buffer.buffer, buffer.size); if (!res) { return tool_rc_general_error; } } else { memcpy(buffer.buffer, inbuffer, buffer.size); } return tpm2_hash(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &buffer, halg, hierarchy, result, validation); } /* * length is either unknown because the FILE * is a fifo, or it's too * big to do in a single hash call. Based on the size figure out the * chunks to loop over, if possible. This way we can call Complete with * data. */ tool_rc rc = tpm2_hash_sequence_start(ectx, &null_auth, halg, &sequence_handle); if (rc != tool_rc_success) { return rc; } /* If we know the file size, we decrement the amount read and terminate * the loop when 1 block is left, else we go till feof. */ done = false; while (!done) { /* if we're using infilep, read the file. Otherwise, directly copy into our local buffer. */ buffer.size = BUFFER_SIZE(typeof(buffer), buffer); if (!!infilep) { bytes_read = fread(buffer.buffer, 1, buffer.size, infilep); if (ferror(infilep)) { LOG_ERR("Error reading from input file"); return tool_rc_general_error; } else { buffer.size = bytes_read; } } else { memcpy(buffer.buffer, inbuffer, buffer.size); inbuffer = inbuffer + buffer.size; } rc = tpm2_sequence_update(ectx, sequence_handle, &buffer); if (rc != tool_rc_success) { return rc; } if (use_left) { left -= buffer.size; if (left <= TPM2_MAX_DIGEST_BUFFER) { done = true; continue; } } else if (!!infilep && feof(infilep)) { done = true; } } /* end file read/hash update loop */ /* if there is data left, get the last bit of data from the file or buffer or set the size to zero */ if (use_left) { buffer.size = left; if (!!infilep) { bool res = files_read_bytes(infilep, buffer.buffer, buffer.size); if (!res) { LOG_ERR("Error reading from input file."); return tool_rc_general_error; } } else { memcpy(buffer.buffer, inbuffer, buffer.size); } } else { buffer.size = 0; } return tpm2_sequence_complete(ectx, sequence_handle, &buffer, hierarchy, result, validation); } tool_rc tpm2_hash_compute_data(ESYS_CONTEXT *ectx, TPMI_ALG_HASH halg, TPMI_RH_HIERARCHY hierarchy, BYTE *buffer, UINT16 length, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { if (!buffer) { return tool_rc_general_error; } return tpm2_hash_common(ectx, halg, hierarchy, NULL, buffer, length, result, validation); } tool_rc tpm2_hash_file(ESYS_CONTEXT *ectx, TPMI_ALG_HASH halg, TPMI_RH_HIERARCHY hierarchy, FILE *input, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { if (!input) { return tool_rc_general_error; } return tpm2_hash_common(ectx, halg, hierarchy, input, NULL, 0, result, validation); } tpm2-tools-5.2/lib/tpm2_hash.h000066400000000000000000000027171412464516500162230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_TPM_HASH_H_ #define SRC_TPM_HASH_H_ #include #include /** * Hashes a BYTE array via the tpm. * @param context * The esapi context. * @param hash_alg * The hashing algorithm to use. * @param hierarchy * The hierarchy. * @param buffer * The data to hash. * @param length * The length of the data. * @param result * The digest result. * @param validation * The validation ticket. Note that some hierarchies don't produce a * validation ticket and thus size will be 0. * @return * A tool_rc indicating status. */ tool_rc tpm2_hash_compute_data(ESYS_CONTEXT *context, TPMI_ALG_HASH halg, TPMI_RH_HIERARCHY hierarchy, BYTE *buffer, UINT16 length, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation); /** * Hashes a FILE * object via the tpm. * @param context * The esapi context. * @param hash_alg * The hashing algorithm to use. * @param hierarchy * The hierarchy. * @param input * The FILE object to hash. * @param result * The digest result. * @param validation * The validation ticket. Note that some hierarchies don't produce a * validation ticket and thus size will be 0. * @return * A tool_rc indicating status. */ tool_rc tpm2_hash_file(ESYS_CONTEXT *ectx, TPMI_ALG_HASH halg, TPMI_RH_HIERARCHY hierarchy, FILE *input, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation); #endif /* SRC_TPM_HASH_H_ */ tpm2-tools-5.2/lib/tpm2_header.h000066400000000000000000000077171412464516500165350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TPM2_HEADER_H #define TPM2_HEADER_H #include #include #include "tpm2_util.h" #define TPM2_COMMAND_HEADER_SIZE (sizeof(tpm2_command_header)) #define TPM2_RESPONSE_HEADER_SIZE (sizeof(tpm2_response_header)) #define TPM2_MAX_SIZE 4096 typedef union tpm2_command_header tpm2_command_header; union tpm2_command_header { struct { TPMI_ST_COMMAND_TAG tag; // uint16 UINT32 size; // TPM2_CC command_code; UINT8 data[]; }__attribute__((packed)); UINT8 bytes[0]; }; typedef union tpm2_response_header tpm2_response_header; union tpm2_response_header { struct { TPM2_ST tag; UINT32 size; TSS2_RC response_code; UINT8 data[]; }__attribute__((packed)); UINT8 bytes[0]; }; /** * Converts a byte-array to a tpm2_command_header struct. * @param h * The byte array to convert to a tpm2_command_header. * @return * A converted byte array. */ static inline tpm2_command_header *tpm2_command_header_from_bytes(UINT8 *h) { return (tpm2_command_header *) h; } /** * Converts a byte-array to a tpm2_response_header struct. * @param h * The byte array to convert to a tpm2_response_header. * @return * A converted byte array. */ static inline tpm2_response_header *tpm2_response_header_from_bytes(UINT8 *h) { return (tpm2_response_header *) h; } /** * Retrieves the command tag from a command converting to host * endianess. * @param command * @return */ static inline TPMI_ST_COMMAND_TAG tpm2_command_header_get_tag( tpm2_command_header *command) { return tpm2_util_ntoh_16(command->tag); } /** * Retrieves the command size from a command converting to host * endianess. * @param command * @param include_header * @return */ static inline UINT32 tpm2_command_header_get_size(tpm2_command_header *command, bool include_header) { UINT32 size = tpm2_util_ntoh_32(command->size); return include_header ? size : size - TPM2_COMMAND_HEADER_SIZE; } /** * Retrieves the command code from a command converting to host * endianess. * @param command * @return */ static inline TPM2_CC tpm2_command_header_get_code(tpm2_command_header *command) { return tpm2_util_ntoh_32(command->command_code); } /** * Retrieves command data, if present. * @param command * The command to check for following data. * @return The command data or NULL if not present. */ static inline UINT8 *tpm2_command_header_get_data(tpm2_command_header *command) { UINT32 size = tpm2_command_header_get_size(command, false); return size ? command->data : NULL; } /** * Retrieves the response size from a response header converting to host * endianess. * @param response_header * @param include_header * @return */ static inline UINT32 tpm2_response_header_get_size( tpm2_response_header *response, bool include_header) { UINT32 size = tpm2_util_ntoh_32(response->size); return include_header ? size : size - TPM2_RESPONSE_HEADER_SIZE; } /** * Retrieves the response tag from a response header converting to host * endianess. * @param response_header * @return */ static inline TPM2_ST tpm2_response_header_get_tag( tpm2_response_header *response) { return tpm2_util_ntoh_16(response->tag); } /** * Retrieves the response code from a response header converting to host * endianess. * @param response_header * @return */ static inline TSS2_RC tpm2_response_header_get_code( tpm2_response_header *response) { return tpm2_util_ntoh_32(response->response_code); } /** * Retrieves response data, if present. * @param response_header * The response_header to check for following data. * @return The response data or NULL if not present. */ static inline UINT8 *tpm2_response_header_get_data( tpm2_response_header *response) { UINT32 size = tpm2_response_header_get_size(response, false); return size ? response->data : NULL; } #endif /* TPM2_HEADER_H */ tpm2-tools-5.2/lib/tpm2_hierarchy.c000066400000000000000000000052131412464516500172430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "log.h" #include "tool_rc.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_alg_util.h" #include "tpm2_hierarchy.h" tool_rc tpm2_hierarchy_create_primary(ESYS_CONTEXT *ectx, tpm2_session *sess, tpm2_hierarchy_pdata *objdata, TPM2B_DIGEST *cp_hash) { ESYS_TR hierarchy; hierarchy = tpm2_tpmi_hierarchy_to_esys_tr(objdata->in.hierarchy); ESYS_TR shandle1 = ESYS_TR_NONE; tool_rc rc = tpm2_auth_util_get_shandle(ectx, hierarchy, sess, &shandle1); if (rc != tool_rc_success) { LOG_ERR("Couldn't get shandle for hierarchy"); return rc; } if (cp_hash) { /* * Need sys_context to be able to calculate CpHash */ TSS2_SYS_CONTEXT *sys_context = NULL; rc = tpm2_getsapicontext(ectx, &sys_context); if(rc != tool_rc_success) { LOG_ERR("Failed to acquire SAPI context."); return rc; } TSS2_RC rval = Tss2_Sys_CreatePrimary_Prepare(sys_context, objdata->in.hierarchy, &objdata->in.sensitive, &objdata->in.public, &objdata->in.outside_info, &objdata->in.creation_pcr); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Tss2_Sys_CreatePrimary_Prepare, rval); return tool_rc_general_error; } TPM2B_NAME *name1 = NULL; rc = tpm2_tr_get_name(ectx, hierarchy, &name1); if (rc != tool_rc_success) { goto tpm2_create_free_name1; } cp_hash->size = tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(sess)); rc = tpm2_sapi_getcphash(sys_context, name1, NULL, NULL, tpm2_session_get_authhash(sess), cp_hash); /* * Exit here without making the ESYS call since we just need the cpHash */ tpm2_create_free_name1: Esys_Free(name1); return rc; } return tpm2_create_primary(ectx, hierarchy, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, &objdata->in.sensitive, &objdata->in.public, &objdata->in.outside_info, &objdata->in.creation_pcr, &objdata->out.handle, &objdata->out.public, &objdata->out.creation.data, &objdata->out.hash, &objdata->out.creation.ticket); } void tpm2_hierarchy_pdata_free(tpm2_hierarchy_pdata *objdata) { free(objdata->out.creation.data); objdata->out.creation.data = NULL; free(objdata->out.creation.ticket); objdata->out.creation.ticket = NULL; free(objdata->out.hash); objdata->out.hash = NULL; free(objdata->out.public); objdata->out.public = NULL; } tpm2-tools-5.2/lib/tpm2_hierarchy.h000066400000000000000000000046451412464516500172600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TOOLS_TPM2_HIERARCHY_H_ #define TOOLS_TPM2_HIERARCHY_H_ #include #include #include "tool_rc.h" #include "tpm2_session.h" typedef struct tpm2_hierarchy_pdata tpm2_hierarchy_pdata; struct tpm2_hierarchy_pdata { struct { TPMI_RH_PROVISION hierarchy; TPM2B_SENSITIVE_CREATE sensitive; TPM2B_PUBLIC public; TPM2B_DATA outside_info; TPML_PCR_SELECTION creation_pcr; ESYS_TR object_handle; } in; struct { ESYS_TR handle; TPM2B_PUBLIC *public; TPM2B_DIGEST *hash; struct { TPM2B_CREATION_DATA *data; TPMT_TK_CREATION *ticket; } creation; } out; }; #define _PUBLIC_AREA_TPMA_OBJECT_DEFAULT_INIT { \ .publicArea = { \ .nameAlg = TPM2_ALG_SHA256, \ .type = TPM2_ALG_RSA, \ .objectAttributes = \ TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT \ |TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT \ |TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH, \ .parameters = { \ .rsaDetail = { \ .exponent = 0, \ .symmetric = { \ .algorithm = TPM2_ALG_AES, \ .keyBits = { .aes = 128 }, \ .mode = { .aes = TPM2_ALG_CFB }, \ }, \ .scheme = { .scheme = TPM2_ALG_NULL }, \ .keyBits = 2048 \ }, \ }, \ .unique = { .rsa = { .size = 0 } } \ }, \ } #define TPM2_HIERARCHY_DATA_INIT { \ .in = { \ .public = _PUBLIC_AREA_TPMA_OBJECT_DEFAULT_INIT, \ .sensitive = TPM2B_SENSITIVE_CREATE_EMPTY_INIT, \ .hierarchy = TPM2_RH_OWNER \ }, \ } /** * Creates a primary object. * @param context * The Enhanced System API (ESAPI) context * @param session * The authorised session for accessing the primary object * @param objdata * The objects data configuration. * @return * tool_rc indicating status. */ tool_rc tpm2_hierarchy_create_primary(ESYS_CONTEXT *context, tpm2_session *sess, tpm2_hierarchy_pdata *objdata, TPM2B_DIGEST *cp_hash); /** * Free allocated memory in a tpm2_hierarchy_pdata structure * * @param objdata * The tpm2_hierarchy_pdata for which to free memory */ void tpm2_hierarchy_pdata_free(tpm2_hierarchy_pdata *objdata); #endif /* TOOLS_TPM2_HIERARCHY_H_ */ tpm2-tools-5.2/lib/tpm2_identity_util.c000066400000000000000000000322141412464516500201540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_identity_util.h" #include "tpm2_kdfa.h" #include "tpm2_kdfe.h" #include "tpm2_openssl.h" // Identity-related functionality that the TPM normally does, but using OpenSSL static TPM2_KEY_BITS get_pub_asym_key_bits(TPM2B_PUBLIC *public) { TPMU_PUBLIC_PARMS *p = &public->publicArea.parameters; switch (public->publicArea.type) { case TPM2_ALG_ECC: /* fall-thru */ case TPM2_ALG_RSA: return p->asymDetail.symmetric.keyBits.sym; /* no default */ } return 0; } static bool share_secret_with_tpm2_rsa_public_key(TPM2B_DIGEST *protection_seed, TPM2B_PUBLIC *parent_pub, const unsigned char *label, int label_len, TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) { bool rval = false; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = convert_pubkey_RSA(&parent_pub->publicArea); if (pkey == NULL) { LOG_ERR("Failed to retrieve public key"); return false; } TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg; /* * RSA Secret Sharing uses a randomly generated seed (Part 1, B.10.3). */ protection_seed->size = tpm2_alg_util_get_hash_size(parent_name_alg); int rc = RAND_bytes(protection_seed->buffer, protection_seed->size); if (rc != 1) { LOG_ERR("Failed to get random bytes"); goto error; } /* * The seed value will be OAEP encrypted with a given L parameter. */ ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ctx) { LOG_ERR("Failed EVP_PKEY_CTX_new"); goto error; } rc = EVP_PKEY_encrypt_init(ctx); if (rc <= 0) { LOG_ERR("Failed EVP_PKEY_encrypt_init"); goto error; } rc = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING); if (rc <= 0) { LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_padding"); goto error; } rc = EVP_PKEY_CTX_set_rsa_oaep_md(ctx, tpm2_openssl_md_from_tpmhalg(parent_name_alg)); if (rc <= 0) { LOG_ERR("Failed EVP_PKEY_CTX_set_rsa_oaep_md"); goto error; } // the library will take ownership of the label char *newlabel = strdup((const char *)label); if (newlabel == NULL) { LOG_ERR("Failed to allocate label"); goto error; } rc = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, newlabel, label_len); if (rc <= 0) { LOG_ERR("Failed EVP_PKEY_CTX_set0_rsa_oaep_label"); free(newlabel); goto error; } size_t outlen = sizeof(TPMU_ENCRYPTED_SECRET); if (EVP_PKEY_encrypt(ctx, encrypted_protection_seed->secret, &outlen, protection_seed->buffer, protection_seed->size) <= 0) { LOG_ERR("Failed EVP_PKEY_encrypt\n"); goto error; } encrypted_protection_seed->size = outlen; rval = true; error: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); return rval; } bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key( TPM2B_PUBLIC *parent_pub, TPM2B_NAME *pubname, TPM2B_DIGEST *protection_seed, TPM2B_MAX_BUFFER *protection_hmac_key, TPM2B_MAX_BUFFER *protection_enc_key) { TPM2B null_2b = { .size = 0 }; TPMI_ALG_HASH parent_alg = parent_pub->publicArea.nameAlg; UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_alg); TSS2_RC rval = tpm2_kdfa(parent_alg, (TPM2B *) protection_seed, "INTEGRITY", &null_2b, &null_2b, parent_hash_size * 8, protection_hmac_key); if (rval != TPM2_RC_SUCCESS) { return false; } TPM2_KEY_BITS pub_key_bits = get_pub_asym_key_bits(parent_pub); rval = tpm2_kdfa(parent_alg, (TPM2B *) protection_seed, "STORAGE", (TPM2B *) pubname, &null_2b, pub_key_bits, protection_enc_key); if (rval != TPM2_RC_SUCCESS) { return false; } return true; } bool tpm2_identity_util_share_secret_with_public_key( TPM2B_DIGEST *protection_seed, TPM2B_PUBLIC *parent_pub, const unsigned char *label, int label_len, TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed) { bool result = false; TPMI_ALG_PUBLIC alg = parent_pub->publicArea.type; switch (alg) { case TPM2_ALG_RSA: result = share_secret_with_tpm2_rsa_public_key(protection_seed, parent_pub, label, label_len, encrypted_protection_seed); break; case TPM2_ALG_ECC: result = ecdh_derive_seed_and_encrypted_seed(parent_pub, label, label_len, protection_seed, encrypted_protection_seed); break; default: LOG_ERR("Cannot handle algorithm, got: %s", tpm2_alg_util_algtostr(alg, tpm2_alg_util_flags_any)); return false; } return result; } static const EVP_CIPHER *tpm_alg_to_ossl(TPMT_SYM_DEF_OBJECT *sym) { switch (sym->algorithm) { case TPM2_ALG_AES: { switch (sym->keyBits.aes) { case 128: return EVP_aes_128_cfb(); case 256: return EVP_aes_256_cfb(); /* no default */ } } /* no default */ } LOG_ERR("Unsupported parent key symmetric parameters"); return NULL; } static bool aes_encrypt_buffers(TPMT_SYM_DEF_OBJECT *sym, uint8_t *encryption_key, uint8_t *buf1, size_t buf1_len, uint8_t *buf2, size_t buf2_len, TPM2B_MAX_BUFFER *cipher_text) { bool result = false; unsigned offset = 0; size_t total_len = buf1_len + buf2_len; if (total_len > sizeof(cipher_text->buffer)) { LOG_ERR("Plaintext too big, got %zu, expected less then %zu", total_len, sizeof(cipher_text->buffer)); return false; } const EVP_CIPHER *cipher = tpm_alg_to_ossl(sym); if (!cipher) { return false; } const unsigned char iv[512] = { 0 }; if (((unsigned long) EVP_CIPHER_iv_length(cipher)) > sizeof(iv)) { LOG_ERR("IV size is bigger then IV buffer size"); return false; } EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); if (!ctx) { return false; } int rc = EVP_EncryptInit_ex(ctx, cipher, NULL, encryption_key, iv); if (!rc) { return false; } EVP_CIPHER_CTX_set_padding(ctx, 0); uint8_t *bufs[2] = { buf1, buf2 }; size_t lens[ARRAY_LEN(bufs)] = { buf1_len, buf2_len }; unsigned i; for (i = 0; i < ARRAY_LEN(bufs); i++) { uint8_t *b = bufs[i]; size_t l = lens[i]; if (!b) { continue; } int output_len = total_len - offset; rc = EVP_EncryptUpdate(ctx, &cipher_text->buffer[offset], &output_len, b, l); if (!rc) { LOG_ERR("Encrypt failed"); goto out; } offset += l; } int tmp_len = 0; rc = EVP_EncryptFinal_ex(ctx, NULL, &tmp_len); if (!rc) { LOG_ERR("Encrypt failed"); goto out; } cipher_text->size = total_len; result = true; out: EVP_CIPHER_CTX_free(ctx); return result; } static void hmac_outer_integrity(TPMI_ALG_HASH parent_name_alg, uint8_t *buffer1, uint16_t buffer1_size, uint8_t *buffer2, uint16_t buffer2_size, uint8_t *hmac_key, TPM2B_DIGEST *outer_integrity_hmac) { uint8_t to_hmac_buffer[TPM2_MAX_DIGEST_BUFFER]; memcpy(to_hmac_buffer, buffer1, buffer1_size); memcpy(to_hmac_buffer + buffer1_size, buffer2, buffer2_size); uint32_t size = 0; UINT16 hash_size = tpm2_alg_util_get_hash_size(parent_name_alg); HMAC(tpm2_openssl_md_from_tpmhalg(parent_name_alg), hmac_key, hash_size, to_hmac_buffer, buffer1_size + buffer2_size, outer_integrity_hmac->buffer, &size); outer_integrity_hmac->size = size; } bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg, TPM2B_SENSITIVE *sensitive, TPM2B_NAME *pubname, TPM2B_DATA *enc_sensitive_key, TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_MAX_BUFFER *encrypted_inner_integrity) { TSS2_RC rval; //Marshal sensitive area uint8_t buffer_marshalled_sensitiveArea[TPM2_MAX_DIGEST_BUFFER] = { 0 }; size_t marshalled_sensitive_size = 0; rval = Tss2_MU_TPMT_SENSITIVE_Marshal(&sensitive->sensitiveArea, buffer_marshalled_sensitiveArea + sizeof(uint16_t), TPM2_MAX_DIGEST_BUFFER, &marshalled_sensitive_size); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the sensitive data"); return false; } size_t marshalled_sensitive_size_info = 0; rval = Tss2_MU_UINT16_Marshal(marshalled_sensitive_size, buffer_marshalled_sensitiveArea, sizeof(uint16_t), &marshalled_sensitive_size_info); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the sensitive size"); return false; } //concatenate NAME memcpy(buffer_marshalled_sensitiveArea + marshalled_sensitive_size + marshalled_sensitive_size_info, pubname->name, pubname->size); //Digest marshalled-sensitive || name uint8_t *marshalled_sensitive_and_name_digest = buffer_marshalled_sensitiveArea + marshalled_sensitive_size + marshalled_sensitive_size_info + pubname->size; size_t digest_size_info = 0; UINT16 hash_size = tpm2_alg_util_get_hash_size(name_alg); rval = Tss2_MU_UINT16_Marshal(hash_size, marshalled_sensitive_and_name_digest, sizeof(uint16_t), &digest_size_info); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the name size"); return false; } const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); if (!md) { LOG_ERR("Algorithm not supported: %x", name_alg); return false; } int rc = EVP_Digest(buffer_marshalled_sensitiveArea, marshalled_sensitive_size_info + marshalled_sensitive_size + pubname->size, marshalled_sensitive_and_name_digest + digest_size_info, NULL, md, NULL); if (!rc) { LOG_ERR("Hash calculation failed"); return false; } //Inner integrity encrypted_inner_integrity->size = marshalled_sensitive_size_info + marshalled_sensitive_size + pubname->size; return aes_encrypt_buffers(sym_alg, enc_sensitive_key->buffer, marshalled_sensitive_and_name_digest, hash_size + digest_size_info, buffer_marshalled_sensitiveArea, marshalled_sensitive_size_info + marshalled_sensitive_size, encrypted_inner_integrity); } void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg, TPM2B_NAME *pubname, TPM2B_MAX_BUFFER *marshalled_sensitive, TPM2B_MAX_BUFFER *protection_hmac_key, TPM2B_MAX_BUFFER *protection_enc_key, TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive, TPM2B_DIGEST *outer_hmac) { //Calculate dupSensitive encrypted_duplicate_sensitive->size = marshalled_sensitive->size; aes_encrypt_buffers(sym_alg, protection_enc_key->buffer, marshalled_sensitive->buffer, marshalled_sensitive->size, NULL, 0, encrypted_duplicate_sensitive); //Calculate outerHMAC hmac_outer_integrity(parent_name_alg, encrypted_duplicate_sensitive->buffer, encrypted_duplicate_sensitive->size, pubname->name, pubname->size, protection_hmac_key->buffer, outer_hmac); } bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname) { /* * A TPM2B_NAME is the name of the algorithm, followed by the hash. * Calculate the name by: * 1. Marshaling the name algorithm * 2. Marshaling the TPMT_PUBLIC past the name algorithm from step 1. * 3. Hash the TPMT_PUBLIC portion in marshaled data. */ TSS2_RC rval; TPMI_ALG_HASH name_alg = public->publicArea.nameAlg; // Step 1 - set beginning of name to hash alg size_t hash_offset = 0; rval = Tss2_MU_UINT16_Marshal(name_alg, pubname->name, pubname->size, &hash_offset); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the name size"); return false; } // Step 2 - marshal TPMTP TPMT_PUBLIC marshaled_tpmt; size_t tpmt_marshalled_size = 0; rval = Tss2_MU_TPMT_PUBLIC_Marshal(&public->publicArea, (uint8_t *) &marshaled_tpmt, sizeof(public->publicArea), &tpmt_marshalled_size); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the public area"); return false; } // Step 3 - Hash the data into name just past the alg type. const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); if (!md) { LOG_ERR("Algorithm not supported: %x", name_alg); return false; } unsigned int hash_size; int rc = EVP_Digest(&marshaled_tpmt, tpmt_marshalled_size, pubname->name + hash_offset, &hash_size, md, NULL); if (!rc) { LOG_ERR("Hash calculation failed"); return false; } //Set the name size, UINT16 followed by HASH pubname->size = hash_size + hash_offset; return true; } tpm2-tools-5.2/lib/tpm2_identity_util.h000066400000000000000000000076061412464516500201700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_IDENTITY_UTIL_H_ #define LIB_TPM2_IDENTITY_UTIL_H_ #include #include #include #include /** * Generates HMAC integrity and symmetric encryption keys for TPM2 identies. * * @param parent_pub * The public key used for seed generation and protection. * @param pubname * The Name object associated with the parent_pub credential. * @param protection_seed * The symmetric seed value used to generate protection keys. * @param protection_hmac_key * The HMAC integrity key to populate. * @param protection_enc_key * The symmetric encryption key to populate. * @return * True on success, false on failure. */ bool tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key( TPM2B_PUBLIC *parent_pub, TPM2B_NAME *pubname, TPM2B_DIGEST *protection_seed, TPM2B_MAX_BUFFER *protection_hmac_key, TPM2B_MAX_BUFFER *protection_enc_key); /** * Encrypts a randomly generated seed with parent public key for TPM2 * credential protection process. * * @param protection_seed * The identity structure protection seed to generate and populate. * @param parent_pub * The public key used for encryption. * @param label * Indicates label for the seed, such as "IDENTITY" or "DUPLICATE". * @param label_len * Length of label. * @param encrypted_protection_seed * The encrypted protection seed to populate. * @return * True on success, false on failure. */ bool tpm2_identity_util_share_secret_with_public_key( TPM2B_DIGEST *protection_seed, TPM2B_PUBLIC *parent_pub, const unsigned char *label, int label_len, TPM2B_ENCRYPTED_SECRET *encrypted_protection_seed); /** * Marshalls Credential Value and encrypts it with the symmetric encryption key. * * @param name_alg * Hash algorithm used to compute Name of the public key. * @param sensitive * The Credential Value to be marshalled and encrypted with symmetric key. * @param pubname * The Name object corresponding to the public key. * @param enc_sensitive_key * The symmetric encryption key. * @param sym_alg * The algorithm used for the symmetric encryption key. * @param encrypted_inner_integrity * The encrypted, marshalled Credential Value to populate. * @return * True on success, false on failure. */ bool tpm2_identity_util_calculate_inner_integrity(TPMI_ALG_HASH name_alg, TPM2B_SENSITIVE *sensitive, TPM2B_NAME *pubname, TPM2B_DATA *enc_sensitive_key, TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_MAX_BUFFER *encrypted_inner_integrity); /** * Encrypts Credential Value with enc key and calculates HMAC with hmac key. * * @param parent_name_alg * Hash algorithm used to compute Name of the public key. * @param pubname * The Name object corresponding to the public key. * @param marshalled_sensitive * Marshalled Credential Value to be encrypted with symmetric encryption key. * @param protection_hmac_key * The HMAC integrity key. * @param protection_enc_key * The symmetric encryption key. * @param sym_alg * The algorithm used for the symmetric encryption key. * @param encrypted_duplicate_sensitive * The encrypted Credential Value to populate. * @param outer_hmac * The outer HMAC structure to populate. */ void tpm2_identity_util_calculate_outer_integrity(TPMI_ALG_HASH parent_name_alg, TPM2B_NAME *pubname, TPM2B_MAX_BUFFER *marshalled_sensitive, TPM2B_MAX_BUFFER *protection_hmac_key, TPM2B_MAX_BUFFER *protection_enc_key, TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive, TPM2B_DIGEST *outer_hmac); /** * Computes the name of a TPM key. * * @param public * Public key structure * @param pubname * The name structure to populate. */ bool tpm2_identity_create_name(TPM2B_PUBLIC *public, TPM2B_NAME *pubname); #endif /* LIB_TPM2_IDENTITY_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_kdfa.c000066400000000000000000000076301412464516500161770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000L #include #else #include #endif #include "log.h" #include "tpm2_kdfa.h" #include "tpm2_openssl.h" TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, TPM2B *context_u, TPM2B *context_v, UINT16 bits, TPM2B_MAX_BUFFER *result_key) { TPM2B_DIGEST tpm2b_label, tpm2b_bits, tpm2b_i_2; TPM2B_DIGEST *buffer_list[8]; TSS2_RC rval = TPM2_RC_SUCCESS; int i, j; UINT16 bytes = bits / 8; result_key->size = 0; tpm2b_i_2.size = 4; tpm2b_bits.size = 4; UINT32 bits_be = tpm2_util_hton_32(bits); memcpy(&tpm2b_bits.buffer[0], &bits_be, sizeof(bits_be)); for(i = 0; label[i] != 0 ;i++ ); tpm2b_label.size = i + 1; for (i = 0; i < tpm2b_label.size; i++) { tpm2b_label.buffer[i] = label[i]; } result_key->size = 0; i = 1; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); if (!md) { LOG_ERR("Algorithm not supported for hmac: %x", hash_alg); return TPM2_RC_HASH; } #if OPENSSL_VERSION_NUMBER < 0x30000000L HMAC_CTX *ctx = HMAC_CTX_new(); #else EVP_MAC *hmac = EVP_MAC_fetch(NULL, "HMAC", NULL); EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(hmac); #endif if (!ctx) { LOG_ERR("HMAC context allocation failed"); return TPM2_RC_MEMORY; } #if OPENSSL_VERSION_NUMBER < 0x30000000L int rc = HMAC_Init_ex(ctx, key->buffer, key->size, md, NULL); #else OSSL_PARAM params[2]; params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, (char *)EVP_MD_get0_name(md), 0); params[1] = OSSL_PARAM_construct_end(); int rc = EVP_MAC_init(ctx, key->buffer, key->size, params); #endif if (!rc) { LOG_ERR("HMAC Init failed: %s", ERR_error_string(rc, NULL)); rval = TPM2_RC_MEMORY; goto err; } // TODO Why is this a loop? It appears to only execute once. while (result_key->size < bytes) { TPM2B_DIGEST tmpResult; // Inner loop bits_be = tpm2_util_hton_32(i); memcpy(&tpm2b_i_2.buffer[0], &bits_be, sizeof(bits_be)); j = 0; buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_i_2); buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_label); buffer_list[j++] = (TPM2B_DIGEST *) context_u; buffer_list[j++] = (TPM2B_DIGEST *) context_v; buffer_list[j++] = (TPM2B_DIGEST *) &(tpm2b_bits); buffer_list[j] = (TPM2B_DIGEST *) 0; int c; for (c = 0; c < j; c++) { TPM2B_DIGEST *digest = buffer_list[c]; #if OPENSSL_VERSION_NUMBER < 0x30000000L int rc = HMAC_Update(ctx, digest->buffer, digest->size); #else int rc = EVP_MAC_update(ctx, digest->buffer, digest->size); #endif if (!rc) { LOG_ERR("HMAC Update failed: %s", ERR_error_string(rc, NULL)); rval = TPM2_RC_MEMORY; goto err; } } #if OPENSSL_VERSION_NUMBER < 0x30000000L unsigned size = sizeof(tmpResult.buffer); int rc = HMAC_Final(ctx, tmpResult.buffer, &size); #else size_t size; int rc = EVP_MAC_final(ctx, tmpResult.buffer, &size, sizeof(tmpResult.buffer)); #endif if (!rc) { LOG_ERR("HMAC Final failed: %s", ERR_error_string(rc, NULL)); rval = TPM2_RC_MEMORY; goto err; } tmpResult.size = size; bool res = tpm2_util_concat_buffer(result_key, (TPM2B *) &tmpResult); if (!res) { rval = TSS2_SYS_RC_BAD_VALUE; goto err; } } // Truncate the result to the desired size. result_key->size = bytes; err: #if OPENSSL_VERSION_NUMBER < 0x30000000L HMAC_CTX_free(ctx); #else EVP_MAC_CTX_free(ctx); EVP_MAC_free(hmac); #endif return rval; } tpm2-tools-5.2/lib/tpm2_kdfa.h000066400000000000000000000007411412464516500162000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_TPM_KDFA_H_ #define SRC_TPM_KDFA_H_ #include /* TODO DOCUMENT ME */ /** * * @param hashAlg * @param key * @param label * @param contextU * @param contextV * @param bits * @param resultKey * @return */ TSS2_RC tpm2_kdfa(TPMI_ALG_HASH hash_alg, TPM2B *key, char *label, TPM2B *context_u, TPM2B *context_v, UINT16 bits, TPM2B_MAX_BUFFER *result_key); #endif /* SRC_TPM_KDFA_H_ */ tpm2-tools-5.2/lib/tpm2_kdfe.c000066400000000000000000000152451412464516500162040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000L #include #else #include #endif #include #include #include "log.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_alg_util.h" #include "tpm2_util.h" TSS2_RC tpm2_kdfe( TPMI_ALG_HASH hash_alg, TPM2B_ECC_PARAMETER *Z, const unsigned char *label, int label_length, TPM2B_ECC_PARAMETER *party_u, TPM2B_ECC_PARAMETER *party_v, UINT16 size_in_bits, TPM2B_MAX_BUFFER *result_key ) { TPM2B_MAX_BUFFER hash_input; TPM2B_DATA use; int bytes = ((size_in_bits + 7) / 8); int done; UINT32 counter, counter_be; UINT16 hash_size = tpm2_alg_util_get_hash_size(hash_alg); TSS2_RC rval = TPM2_RC_SUCCESS; memcpy(use.buffer, label, label_length); use.size = label_length; /* * Hash[i] := H(hash_input), where otherInfo := Use | PartyUInfo|PartyVInfo * hash_input := counter | Z | OtherInfo */ hash_input.size = 4; // room for the counter tpm2_util_concat_buffer(&hash_input, (TPM2B *) Z); tpm2_util_concat_buffer(&hash_input, (TPM2B *) &use); tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_u); tpm2_util_concat_buffer(&hash_input, (TPM2B *) party_v); const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); if (!md) { LOG_ERR("Algorithm not supported: %x", hash_alg); return TPM2_RC_HASH; } for (done = 0, counter = 1; done < bytes; done += hash_size, counter++) { counter_be = tpm2_util_hton_32(counter); memcpy(hash_input.buffer, &counter_be, 4); int rc = EVP_Digest(hash_input.buffer, hash_input.size, result_key->buffer + done, NULL, md, NULL); if (!rc) { LOG_ERR("Hash calculation failed"); return TPM2_RC_MEMORY; } } // truncate the result to the desired size result_key->size = bytes; return rval; } static bool get_public_key_from_ec_key(EVP_PKEY *pkey, TPMS_ECC_POINT *point) { BIGNUM *x = NULL; BIGNUM *y = NULL; unsigned int nbx, nby; bool result = false; #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *key = EVP_PKEY_get0_EC_KEY(pkey); const EC_POINT *pubkey = EC_KEY_get0_public_key(key); x = BN_new(); y = BN_new(); if ((x == NULL) || (y == NULL) || (pubkey == NULL)) { LOG_ERR("Failed to allocate memory to store EC public key."); goto out; } EC_POINT_get_affine_coordinates_tss(EC_KEY_get0_group(key), pubkey, x, y, NULL); #else int rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &x); if (!rc) { LOG_ERR("Failed to get EC public key X."); goto out; } rc = EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &y); if (!rc) { LOG_ERR("Failed to get EC public key Y."); goto out; } #endif nbx = BN_num_bytes(x); nby = BN_num_bytes(y); if ((nbx > sizeof(point->x.buffer))|| (nby > sizeof(point->y.buffer))) { LOG_ERR("EC public key has too many bits."); goto out; } point->x.size = nbx; point->y.size = nby; BN_bn2bin(x, point->x.buffer); BN_bn2bin(y, point->y.buffer); result = true; out: BN_free(x); BN_free(y); return result; } static int get_ECDH_shared_secret(EVP_PKEY *pkey, EVP_PKEY *p_pub, TPM2B_ECC_PARAMETER *secret) { EVP_PKEY_CTX *ctx; int result = -1; ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!ctx) return -1; int rc = EVP_PKEY_derive_init(ctx); if (rc <= 0) goto out; rc = EVP_PKEY_derive_set_peer(ctx, p_pub); if (rc <= 0) goto out; size_t shared_secret_length = sizeof(secret->buffer); rc = EVP_PKEY_derive(ctx, secret->buffer, &shared_secret_length); if (rc <= 0) goto out; secret->size = shared_secret_length; result = secret->size; out: EVP_PKEY_CTX_free(ctx); return result; } bool ecdh_derive_seed_and_encrypted_seed( TPM2B_PUBLIC *parent_pub, const unsigned char *label, int label_len, TPM2B_DIGEST *seed, TPM2B_ENCRYPTED_SECRET *out_sym_seed) { TPMS_ECC_PARMS *tpm_ecc = &parent_pub->publicArea.parameters.eccDetail; TPMI_ALG_HASH parent_name_alg = parent_pub->publicArea.nameAlg; UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_name_alg); bool result = false; EVP_PKEY_CTX *ctx; EVP_PKEY *pkey = NULL; EVP_PKEY *qsv = NULL; TPMS_ECC_POINT qeu; bool qeu_is_valid; TPM2B_ECC_PARAMETER ecc_secret; // generate an ephemeral key int nid = tpm2_ossl_curve_to_nid(tpm_ecc->curveID); ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!ctx) { LOG_ERR("Failed to create key creation context"); return false; } int rc = EVP_PKEY_keygen_init(ctx); if (rc <= 0) { LOG_ERR("Failed to initialize key creation"); goto out; } rc = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); if (rc <= 0) { LOG_ERR("Failed to set EC curve NID %i", nid); goto out; } rc = EVP_PKEY_keygen(ctx, &pkey); if (rc <= 0) { LOG_ERR("Failed to generate the ephemeral EC key"); goto out; } // get public key for the ephemeral key qeu_is_valid = get_public_key_from_ec_key(pkey, &qeu); if (qeu_is_valid == false) { LOG_ERR("Could not get the ECC public key"); goto out; } /* marshal the public key to encrypted seed */ size_t offset = 0; TSS2_RC rval; rval = Tss2_MU_TPMS_ECC_POINT_Marshal(&qeu, out_sym_seed->secret, sizeof(out_sym_seed->secret), &offset); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing the ECC public key"); goto out; } out_sym_seed->size = offset; /* get parents public key */ qsv = convert_pubkey_ECC(&parent_pub->publicArea); if (qsv == NULL) { LOG_ERR("Could not get parent's public key"); goto out; } rc = get_ECDH_shared_secret(pkey, qsv, &ecc_secret); if (rc <= 0) { LOG_ERR("Could not derive shared secret"); goto out; } /* derive seed using KDFe */ TPM2B_ECC_PARAMETER *party_u_info = &qeu.x; TPM2B_ECC_PARAMETER *party_v_info = &parent_pub->publicArea.unique.ecc.x; tpm2_kdfe(parent_name_alg, &ecc_secret, label, label_len, party_u_info, party_v_info, parent_hash_size * 8, (TPM2B_MAX_BUFFER *) seed); result = true; out: EVP_PKEY_free(qsv); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return result; } tpm2-tools-5.2/lib/tpm2_kdfe.h000066400000000000000000000037561412464516500162150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_TPM_KDFE_H_ #define SRC_TPM_KDFE_H_ #include /** * The KDFe function, defined in Appendix C.6.1 of TPM 2.0 Library * Specification Part1 * (https://trustedcomputinggroup.org/resource/tpm-library-specification/) * * @param hash_alg * The hashing algorithm to use. * @param Z * The ECDH shared secret. Z is the x coordinate of the product of d and Q, * where d is a private key and Q is the other party's public key. * @param label * The label value. ie. "DUPLICATE\0" or "IDENTITY\0". * @param label_length * Length of the label. * @param party_u_info * The x-coordinate of the public key * @param party_v_info * The x-coordinate of the other party's public key * @param size_in_bits * The number of bits of the key stream to be generated * @param result_key * The buffer to write the generated key stream * @return * TPM2_RC_SUCCESS on success */ TSS2_RC tpm2_kdfe( TPMI_ALG_HASH hash_alg, TPM2B_ECC_PARAMETER *Z, const unsigned char *label, int label_length, TPM2B_ECC_PARAMETER *party_u_info, TPM2B_ECC_PARAMETER *party_v_info, UINT16 size_in_bits, TPM2B_MAX_BUFFER *result_key ); /** * Derive the seed value and protected seed value, as specified * in Appendix C.6.3 of TPM 2.0 Library Specification Part1 * (https://trustedcomputinggroup.org/resource/tpm-library-specification/) * * @param[in] parent_pub * The parents ECC public key. * @param[in] label * The label value. ie. "DUPLICATE\0" or "IDENTITY\0". * @param[in] label_len * Length of the label. * @param[out] seed * The derived seed value * @param[out] out_sym_seed * protedted seed value, ie the public key for the ephemeral key. * @return * True on success, false otherwise. */ bool ecdh_derive_seed_and_encrypted_seed( TPM2B_PUBLIC *parent_pub, const unsigned char *label, int label_len, TPM2B_DIGEST *seed, TPM2B_ENCRYPTED_SECRET *out_sym_seed); #endif /* SRC_TPM_KDFE_H_ */ tpm2-tools-5.2/lib/tpm2_nv_util.h000066400000000000000000000220271412464516500167540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_NV_UTIL_H_ #define LIB_TPM2_NV_UTIL_H_ #include #include #include "log.h" #include "tpm2.h" #include "tpm2_capability.h" #include "tpm2_session.h" #include "tpm2_auth_util.h" #include "tpm2_hierarchy.h" #include "tpm2_util.h" /** * Reads the public portion of a Non-Volatile (nv) index. * @param context * The ESAPI context. * @param nv_index * The index to read. * @param nv_public * The public data structure to store the results in. * @return * tool_rc indicating status. */ static inline tool_rc tpm2_util_nv_read_public(ESYS_CONTEXT *context, TPMI_RH_NV_INDEX nv_index, TPM2B_NV_PUBLIC **nv_public) { ESYS_TR tr_object; tool_rc rc = tpm2_from_tpm_public(context, nv_index, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &tr_object); if (rc != tool_rc_success) { return rc; } rc = tpm2_nv_readpublic(context, tr_object, nv_public, NULL); tool_rc tmp_rc = tpm2_close(context, &tr_object); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } return rc; } /** * Retrieves max NV buffer size based on the NV operation and accounting for the * buffers reported by the capability structures. * 1. If getcap fails, return TPM2_MAX_NV_BUFFER_SIZE constant * 2. If getcap passes AND op is NVDEFINE return TPM2_PT_NV_INDEX_MAX cap data * 3. if getcap passes AND op is !NVDEFINE return TPM2_PT_NV_BUFFER cap data * * @param esys_context * The Enhanced System API (ESAPI) context * @param is_nvdefine_op * Truth value to check if the NV operation is for defining NV index. * @return * The maximum allowed NV size based on the NV operation and capability info. */ static inline uint16_t tpm2_nv_util_max_allowed_nv_size( ESYS_CONTEXT *esys_context, bool is_nvdefine_op) { /* * 1. Default size if getcap fails to report */ uint16_t max_nv_size = TPM2_MAX_NV_BUFFER_SIZE; TPMS_CAPABILITY_DATA *cap_data = 0; UINT32 property = is_nvdefine_op ? TPM2_PT_FIXED : TPM2_PT_NV_BUFFER_MAX; UINT32 property_count = is_nvdefine_op ? TPM2_MAX_TPM_PROPERTIES : 1; tool_rc rc = tpm2_getcap(esys_context, TPM2_CAP_TPM_PROPERTIES, property, property_count, 0, &cap_data); bool is_getcap_op_fail = false; if (rc != tool_rc_success) { is_getcap_op_fail = true; goto out; } /* * 2. Non-NVDEFINE ops */ if (!is_nvdefine_op) { if(cap_data->data.tpmProperties.tpmProperty[0].property == TPM2_PT_NV_BUFFER_MAX ) { max_nv_size = cap_data->data.tpmProperties.tpmProperty[0].value; } else { /* * If TPM doesn't report TPM2_PT_NV_BUFFER_MAX in getcap, * set the default sz. */ is_getcap_op_fail = true; } goto out; } /* * 3. NVDEFINE op */ TPMS_TAGGED_PROPERTY *properties = cap_data->data.tpmProperties.tpmProperty; UINT32 count = cap_data->data.tpmProperties.count; if (!count) { is_getcap_op_fail = true; goto out; } /* * If TPM doesn't report TPM2_PT_NV_INDEX_MAX in getcap, set the default sz. */ is_getcap_op_fail = true; UINT32 i; for (i = 0; i < count; i++) { if (properties[i].property == TPM2_PT_NV_INDEX_MAX) { max_nv_size = properties[i].value; is_getcap_op_fail = false; break; } } out: free(cap_data); if (is_getcap_op_fail) { LOG_WARN("Cannot determine size from TPM properties." "Setting max NV index size value to TPM2_MAX_NV_BUFFER_SIZE"); } return max_nv_size; } /** * Reads data at Non-Volatile (nv) index. * @param ectx * The ESAPI context. * @param nv_index * The index to read. * @param size * The number of bytes to read. * @param offset * Offset (in bytes) from which to start reading. * @param hierarchy * TPMI_RH_NV hierarchy value. * @param sdata * Session authorization * @param sess * tpm2 session. * @param data_buffer * (callee-allocated) Buffer containing data at nv_index * @param bytes_read * The number of bytes written to data_buffer * @return * tool_rc indicating status. */ static inline tool_rc tpm2_util_nv_read(ESYS_CONTEXT *ectx, TPMI_RH_NV_INDEX nv_index, UINT16 size, UINT16 offset, tpm2_loaded_object * auth_hierarchy_obj, UINT8 **data_buffer, UINT16 *bytes_read, TPM2B_DIGEST *cp_hash, TPM2B_DIGEST *rp_hash, TPMI_ALG_HASH parameter_hash_algorithm, TPM2B_NAME *precalc_nvname, ESYS_TR shandle2, ESYS_TR shandle3) { /* * NVRead is not dispatched when: * cpHash size is non-zero and rpHash size is zero. */ bool is_nvread_dispatched = (cp_hash->size && !rp_hash->size)? false : true; UINT16 max_data_size = 0; if (!is_nvread_dispatched) { *data_buffer = 0; max_data_size = size; } /* * Perform additional checks on the NV index size when actually dispatching * NVRead command. */ tool_rc rc = tool_rc_success; if (is_nvread_dispatched) { max_data_size= tpm2_nv_util_max_allowed_nv_size(ectx, false); TPM2B_NV_PUBLIC *nv_public = NULL; rc = tpm2_util_nv_read_public(ectx, nv_index, &nv_public); if (rc != tool_rc_success) { goto out; } UINT16 data_size = nv_public->nvPublic.dataSize; free(nv_public); /* if size is 0, assume the whole object */ if (size == 0) { size = data_size; } if (offset > data_size) { LOG_ERR("Requested offset to read from is greater than size. offset=%u" ", size=%u", offset, data_size); rc = tool_rc_general_error; goto out; } if (offset + size > data_size) { LOG_ERR("Requested to read more bytes than available from offset," " offset=%u, request-read-size=%u actual-data-size=%u", offset, size, data_size); rc = tool_rc_general_error; goto out; } *data_buffer = malloc(data_size); if (!*data_buffer) { LOG_ERR("oom"); rc = tool_rc_general_error; goto out; } } bool is_nv_index_data_larger_than_max_read = (size > max_data_size); /* * The cpHash will also be calculated when rpHash is not zero and command is * actually dispatched. So we want to make sure that if size is not * specified, the NV read operation defaulting to read the entire NV index, * must not cause cpHash buffer to be overwritten. This is becuase in such a * case the NV read is broken into two seperate calls due to the buffer size * being larger than the maximum NV read access size. */ if ((cp_hash->size || rp_hash->size) && is_nv_index_data_larger_than_max_read) { LOG_ERR("Cannot continue to avoid overwriting cpHash/rphash data in file. " "Make seperate tpm2_nvread calls with proper offsets specified to " "specify all NV index data to be read"); rc =-tool_rc_option_error; goto out; } UINT16 data_buffer_offset = 0; while (size > 0) { UINT16 bytes_to_read = size > max_data_size ? max_data_size : size; TPM2B_MAX_NV_BUFFER *nv_data; rc = tpm2_nv_read(ectx, auth_hierarchy_obj, nv_index, precalc_nvname, bytes_to_read, offset, &nv_data, cp_hash, rp_hash, parameter_hash_algorithm, shandle2, shandle3); if (rc != tool_rc_success) { if (rc != tool_rc_option_error) { LOG_ERR("Failed to read NVRAM area at index 0x%X", nv_index); } goto out; } if (is_nvread_dispatched) { size -= nv_data->size; offset += nv_data->size; memcpy(*data_buffer + data_buffer_offset, nv_data->buffer, nv_data->size); data_buffer_offset += nv_data->size; free(nv_data); } else { /* * When calculating cpHash the full size is already considered and * so there is no need to adjust it. */ size = 0; } } if (is_nvread_dispatched && bytes_read) { *bytes_read = data_buffer_offset; } out: if (rc != tool_rc_success && *data_buffer != NULL) { free(*data_buffer); *data_buffer = NULL; } return rc; } static inline bool on_arg_nv_index(int argc, char **argv, TPMI_RH_NV_INDEX *nv_index) { if (argc > 1) { LOG_ERR("Specify single value for NV Index"); return false; } if (!argc) { LOG_ERR("Specify at least a single value for NV Index"); return false; } bool result = tpm2_util_handle_from_optarg(argv[0], nv_index, TPM2_HANDLE_FLAGS_NV); if (!result) { LOG_ERR("Could not convert NV index to number, got: \"%s\"", argv[0]); return false; } if (*nv_index == 0) { LOG_ERR("NV Index cannot be 0"); return false; } return true; } #endif /* LIB_TPM2_NV_UTIL_H_ */ tpm2-tools-5.2/lib/tpm2_openssl.c000066400000000000000000001040551412464516500167540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #if OPENSSL_VERSION_NUMBER < 0x30000000L #include #else #include #endif #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_attr_util.h" #include "tpm2_identity_util.h" #include "tpm2_openssl.h" #include "tpm2_errata.h" #include "tpm2_systemdeps.h" #define KEYEDHASH_MAX_SIZE 128 #define HMAC_MAX_SIZE 64 int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm) { switch (algorithm) { case TPM2_ALG_SHA1: return NID_sha1; case TPM2_ALG_SHA256: return NID_sha256; case TPM2_ALG_SHA384: return NID_sha384; case TPM2_ALG_SHA512: return NID_sha512; default: return NID_sha256; } /* no return, not possible */ } const EVP_MD *tpm2_openssl_md_from_tpmhalg(TPMI_ALG_HASH algorithm) { switch (algorithm) { case TPM2_ALG_SHA1: return EVP_sha1(); case TPM2_ALG_SHA256: return EVP_sha256(); case TPM2_ALG_SHA384: return EVP_sha384(); case TPM2_ALG_SHA512: return EVP_sha512(); default: return NULL; } /* no return, not possible */ } bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest) { bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); if (!md) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } rc = EVP_DigestUpdate(mdctx, buffer, length); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } digest->size = size; result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, const BYTE *data, UINT16 length) { bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); if (!md) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } // extend operation is pcr = HASH(pcr + data) unsigned size = EVP_MD_size(md); rc = EVP_DigestUpdate(mdctx, pcr, size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } rc = EVP_DigestUpdate(mdctx, data, length); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } rc = EVP_DigestFinal_ex(mdctx, pcr, &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, TPM2B_DIGEST *digest) { bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); if (!md) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } size_t i; for (i = 0; i < digests->count; i++) { TPM2B_DIGEST *b = &digests->digests[i]; rc = EVP_DigestUpdate(mdctx, b->buffer, b->size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } } unsigned size = EVP_MD_size(EVP_sha256()); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } digest->size = size; result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } // show all PCR banks according to g_pcrSelection & g_pcrs-> bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest) { UINT32 vi = 0, di = 0, i; bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); if (!md) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } // Loop through all PCR/hash banks for (i = 0; i < pcr_select->count; i++) { // Loop through all PCRs in this bank unsigned int pcr_id; for (pcr_id = 0; pcr_id < pcr_select->pcrSelections[i].sizeofSelect * 8u; pcr_id++) { if (!tpm2_util_is_pcr_select_bit_set(&pcr_select->pcrSelections[i], pcr_id)) { // skip non-selected banks continue; } if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) { LOG_ERR("Something wrong, trying to print but nothing more"); goto out; } // Update running digest (to compare with quote) TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di]; rc = EVP_DigestUpdate(mdctx, b->buffer, b->size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } if (++di < pcrs->pcr_values[vi].count) { continue; } di = 0; if (++vi < pcrs->count) { continue; } } } // Finalize running digest unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } digest->size = size; result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } /* show all PCR banks according to g_pcrSelection & g_pcrs-> */ bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hash_alg, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest) { UINT32 vi = 0, di = 0, i; bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(hash_alg); if (!md) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } /* Loop through all PCR/hash banks */ for (i = 0; i < le32toh(pcr_select->count); i++) { /* Loop through all PCRs in this bank */ unsigned int pcr_id; for (pcr_id = 0; pcr_id < pcr_select->pcrSelections[i].sizeofSelect * 8u; pcr_id++) { if (!tpm2_util_is_pcr_select_bit_set(&pcr_select->pcrSelections[i], pcr_id)) { continue; // skip non-selected banks } if (vi >= le64toh(pcrs->count) || di >= le32toh(pcrs->pcr_values[vi].count)) { LOG_ERR("Something wrong, trying to print but nothing more"); goto out; } /* Update running digest (to compare with quote) */ TPM2B_DIGEST *b = &pcrs->pcr_values[vi].digests[di]; rc = EVP_DigestUpdate(mdctx, b->buffer, le16toh(b->size)); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } if (++di < le32toh(pcrs->pcr_values[vi].count)) { continue; } di = 0; if (++vi < le64toh(pcrs->count)) { continue; } } } /* Finalize running digest */ unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, digest->buffer, &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } digest->size = size; result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } /* * Per man openssl(1), handle the following --passin formats: * pass:password * the actual password is password. Since the password is visible to utilities (like 'ps' under Unix) this form should only be used where security is not * important. * * env:var obtain the password from the environment variable var. Since the environment of other processes is visible on certain platforms (e.g. ps under certain * Unix OSes) this option should be used with caution. * * file:pathname * the first line of pathname is the password. If the same pathname argument is supplied to -passin and -passout arguments then the first line will be used * for the input password and the next line for the output password. pathname need not refer to a regular file: it could for example refer to a device or * named pipe. * * fd:number read the password from the file descriptor number. This can be used to send the data via a pipe for example. * * stdin read the password from standard input. * */ typedef bool (*pfn_ossl_pw_handler)(const char *passin, char **pass); static bool do_pass(const char *passin, char **pass) { char *tmp = strdup(passin); if (!tmp) { LOG_ERR("oom"); return false; } *pass = tmp; return true; } static bool do_env(const char *envvar, char **pass) { char *tmp = getenv(envvar); if (!tmp) { LOG_ERR("Environment variable \"%s\" not found", envvar); return false; } tmp = strdup(tmp); if (!tmp) { LOG_ERR("oom"); return false; } *pass = tmp; return true; } static bool do_open_file(FILE *f, const char *path, char **pass) { bool rc = false; unsigned long file_size = 0; bool result = files_get_file_size(f, &file_size, path); if (!result) { goto out; } if (file_size + 1 <= file_size) { LOG_ERR("overflow: file_size too large"); goto out; } char *tmp = calloc(sizeof(char), file_size + 1); if (!tmp) { LOG_ERR("oom"); goto out; } result = files_read_bytes(f, (UINT8 *) tmp, file_size); if (!result) { free(tmp); goto out; } *pass = tmp; rc = true; out: fclose(f); return rc; } static bool do_file(const char *path, char **pass) { FILE *f = fopen(path, "rb"); if (!f) { LOG_ERR("could not open file \"%s\" error: %s", path, strerror(errno)); return false; } return do_open_file(f, path, pass); } static bool do_fd(const char *passin, char **pass) { char *end_ptr = NULL; int fd = strtoul(passin, &end_ptr, 0); if (passin[0] != '\0' && end_ptr[0] != '\0') { LOG_ERR("Invalid fd, got: \"%s\"", passin); return false; } FILE *f = fdopen(fd, "rb"); if (!f) { LOG_ERR("could not open fd \"%d\" error: %s", fd, strerror(errno)); return false; } return do_open_file(f, "fd", pass); } static bool do_stdin(const char *passin, char **pass) { UNUSED(passin); void *buf = calloc(sizeof(BYTE), UINT16_MAX + 1); if (!buf) { LOG_ERR("oom"); return false; } UINT16 size = UINT16_MAX; bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, NULL, &size, buf); if (!result) { free(buf); return false; } *pass = buf; return true; } static bool handle_ossl_pass(const char *passin, char **pass) { pfn_ossl_pw_handler pfn = NULL; if (!passin) { *pass = NULL; return true; } if (!strncmp("pass:", passin, 5)) { passin += 5; pfn = do_pass; } else if (!strncmp("env:", passin, 4)) { pfn = do_env; passin += 4; } else if (!strncmp("file:", passin, 5)) { pfn = do_file; passin += 5; } else if (!strncmp("fd:", passin, 3)) { pfn = do_fd; passin += 3; } else if (!strcmp("stdin", passin)) { pfn = do_stdin; } else { LOG_ERR("Unknown OSSL style password argument, got: \"%s\"", passin); return false; } return pfn(passin, pass); } static bool load_public_RSA_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) { bool result = false; TPMT_PUBLIC *pt = &pub->publicArea; pt->type = TPM2_ALG_RSA; TPMS_RSA_PARMS *rdetail = &pub->publicArea.parameters.rsaDetail; rdetail->scheme.scheme = TPM2_ALG_NULL; rdetail->symmetric.algorithm = TPM2_ALG_NULL; rdetail->scheme.details.anySig.hashAlg = TPM2_ALG_NULL; /* NULL out sym details */ TPMT_SYM_DEF_OBJECT *sym = &rdetail->symmetric; sym->algorithm = TPM2_ALG_NULL; sym->keyBits.sym = 0; sym->mode.sym = TPM2_ALG_NULL; #if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *n; /* modulus */ const BIGNUM *e; /* public key exponent */ RSA *k = EVP_PKEY_get0_RSA(key); if (!k) { LOG_ERR("Could not retrieve RSA key"); goto out; } RSA_get0_key(k, &n, &e, NULL); #else BIGNUM *n = NULL; /* modulus */ BIGNUM *e = NULL; /* public key exponent */ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_N, &n); if (!rc) { LOG_ERR("Could not read public modulus N"); goto out; } rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_E, &e); if (!rc) { LOG_ERR("Could not read public exponent E"); goto out; } #endif /* * The size of the modulus is the key size in RSA, store this as the * keyBits in the RSA details. */ rdetail->keyBits = BN_num_bytes(n) * 8; switch (rdetail->keyBits) { case 1024: /* falls-through */ case 2048: /* falls-through */ case 4096: /* falls-through */ break; default: LOG_ERR("RSA key-size %u is not supported", rdetail->keyBits); goto out; } /* copy the modulus to the unique RSA field */ pt->unique.rsa.size = rdetail->keyBits / 8; int success = BN_bn2bin(n, pt->unique.rsa.buffer); if (!success) { LOG_ERR("Could not copy public modulus N"); goto out; } unsigned long exp = BN_get_word(e); if (exp == 0xffffffffL) { LOG_ERR("Could not copy public exponent E"); goto out; } rdetail->exponent = exp; result = true; out: #if OPENSSL_VERSION_NUMBER < 0x30000000L /* k,n,e point to internal structrues and must not be freed after use */ #else BN_free(n); BN_free(e); #endif return result; } static bool load_public_RSA_from_pem(FILE *f, const char *path, TPM2B_PUBLIC *pub) { /* * Public PEM files appear in two formats: * 1. PEM format, read with PEM_read_RSA_PUBKEY * 2. PKCS#1 format, read with PEM_read_RSAPublicKey * * See: * - https://stackoverflow.com/questions/7818117/why-i-cant-read-openssl-generated-rsa-pub-key-with-pem-read-rsapublickey */ EVP_PKEY *k = PEM_read_PUBKEY(f, NULL, NULL, NULL); if (!k) { ERR_print_errors_fp(stderr); LOG_ERR("Reading public PEM file \"%s\" failed", path); return false; } bool result = false; if (EVP_PKEY_base_id(k) == EVP_PKEY_RSA) { result = load_public_RSA_from_key(k, pub); } EVP_PKEY_free(k); return result; } static const struct { TPMI_ECC_CURVE curve; int nid; } nid_curve_map[] = { { TPM2_ECC_NIST_P192, NID_X9_62_prime192v1 }, { TPM2_ECC_NIST_P224, NID_secp224r1 }, { TPM2_ECC_NIST_P256, NID_X9_62_prime256v1 }, { TPM2_ECC_NIST_P384, NID_secp384r1 }, { TPM2_ECC_NIST_P521, NID_secp521r1 } /* * XXX * See if it's possible to support the other curves, I didn't see the * mapping in OSSL: * - TPM2_ECC_BN_P256 * - TPM2_ECC_BN_P638 * - TPM2_ECC_SM2_P256 */ }; /** * Maps an OSSL nid as defined obj_mac.h to a TPM2 ECC curve id. * @param nid * The nid to map. * @return * A valid TPM2_ECC_* or TPM2_ALG_ERROR on error. */ static TPMI_ECC_CURVE ossl_nid_to_curve(int nid) { unsigned i; for (i = 0; i < ARRAY_LEN(nid_curve_map); i++) { TPMI_ECC_CURVE c = nid_curve_map[i].curve; int n = nid_curve_map[i].nid; if (n == nid) { return c; } } LOG_ERR("Cannot map nid \"%d\" to TPM ECC curve", nid); return TPM2_ALG_ERROR; } int tpm2_ossl_curve_to_nid(TPMI_ECC_CURVE curve) { unsigned i; for (i = 0; i < ARRAY_LEN(nid_curve_map); i++) { TPMI_ECC_CURVE c = nid_curve_map[i].curve; int n = nid_curve_map[i].nid; if (c == curve) { return n; } } LOG_ERR("Cannot map TPM ECC curve \"%u\" to nid", curve); return -1; } static bool load_public_ECC_from_key(EVP_PKEY *key, TPM2B_PUBLIC *pub) { BIGNUM *y = NULL; BIGNUM *x = NULL; int nid; unsigned keysize; bool result = false; /* * Set the algorithm type */ pub->publicArea.type = TPM2_ALG_ECC; TPMS_ECC_PARMS *pp = &pub->publicArea.parameters.eccDetail; /* * Get the curve type and the public key (X and Y) */ #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *k = EVP_PKEY_get0_EC_KEY(key); if (!k) { LOG_ERR("Could not retrieve ECC key"); goto out; } y = BN_new(); x = BN_new(); if (!x || !y) { LOG_ERR("oom"); goto out; } const EC_GROUP *group = EC_KEY_get0_group(k); nid = EC_GROUP_get_curve_name(group); keysize = (EC_GROUP_get_degree(group) + 7) / 8; const EC_POINT *point = EC_KEY_get0_public_key(k); int ret = EC_POINT_get_affine_coordinates_tss(group, point, x, y, NULL); if (!ret) { LOG_ERR("Could not get X and Y affine coordinates"); goto out; } #else char curve_name[80]; int rc = EVP_PKEY_get_utf8_string_param(key, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, sizeof(curve_name), NULL); if (!rc) { LOG_ERR("Could not read ECC curve name"); goto out; } nid = OBJ_txt2nid(curve_name); keysize = (EVP_PKEY_bits(key) + 7) / 8; rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_X, &x); if (!rc) { LOG_ERR("Could not read public X coordinate"); goto out; } rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_EC_PUB_Y, &y); if (!rc) { LOG_ERR("Could not read public Y coordinate"); goto out; } #endif /* * Set the curve type */ TPM2_ECC_CURVE curve_id = ossl_nid_to_curve(nid); // Not sure what lines up with NIST 256... if (curve_id == TPM2_ALG_ERROR) { goto out; } pp->curveID = curve_id; /* * Copy the X and Y coordinate data into the ECC unique field, * ensuring that it fits along the way. */ TPM2B_ECC_PARAMETER *X = &pub->publicArea.unique.ecc.x; TPM2B_ECC_PARAMETER *Y = &pub->publicArea.unique.ecc.y; if (keysize > sizeof(X->buffer)) { LOG_ERR("X coordinate is too big. Got %u expected less than or equal to" " %zu", keysize, sizeof(X->buffer)); goto out; } if (keysize > sizeof(Y->buffer)) { LOG_ERR("X coordinate is too big. Got %u expected less than or equal to" " %zu", keysize, sizeof(Y->buffer)); goto out; } X->size = BN_bn2binpad(x, X->buffer, keysize); if (X->size != keysize) { LOG_ERR("Error converting X point BN to binary"); goto out; } Y->size = BN_bn2binpad(y, Y->buffer, keysize); if (Y->size != keysize) { LOG_ERR("Error converting Y point BN to binary"); goto out; } /* * no kdf - not sure what this should be */ pp->kdf.scheme = TPM2_ALG_NULL; pp->scheme.scheme = TPM2_ALG_NULL; pp->symmetric.algorithm = TPM2_ALG_NULL; pp->scheme.details.anySig.hashAlg = TPM2_ALG_NULL; /* NULL out sym details */ TPMT_SYM_DEF_OBJECT *sym = &pp->symmetric; sym->algorithm = TPM2_ALG_NULL; sym->keyBits.sym = 0; sym->mode.sym = TPM2_ALG_NULL; result = true; out: BN_free(x); BN_free(y); return result; } static bool load_public_ECC_from_pem(FILE *f, const char *path, TPM2B_PUBLIC *pub) { EVP_PKEY *k = PEM_read_PUBKEY(f, NULL, NULL, NULL); if (!k) { ERR_print_errors_fp(stderr); LOG_ERR("Reading PEM file \"%s\" failed", path); return false; } bool result = false; if (EVP_PKEY_base_id(k) == EVP_PKEY_EC) { result = load_public_ECC_from_key(k, pub); } EVP_PKEY_free(k); return result; } static bool load_public_AES_from_file(FILE *f, const char *path, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { /* * Get the file size and validate that it is the proper AES keysize. */ unsigned long file_size = 0; bool result = files_get_file_size(f, &file_size, path); if (!result) { return false; } result = tpm2_alg_util_is_aes_size_valid(file_size); if (!result) { return false; } pub->publicArea.type = TPM2_ALG_SYMCIPHER; TPMT_SYM_DEF_OBJECT *s = &pub->publicArea.parameters.symDetail.sym; s->algorithm = TPM2_ALG_AES; s->keyBits.aes = file_size * 8; /* allow any mode later on */ s->mode.aes = TPM2_ALG_NULL; /* * Calculate the unique field with is the * is HMAC(sensitive->seedValue, sensitive->sensitive(key itself)) * Where: * - HMAC Key is the seed * - Hash algorithm is the name algorithm */ TPM2B_DIGEST *unique = &pub->publicArea.unique.sym; TPM2B_DIGEST *seed = &priv->sensitiveArea.seedValue; TPM2B_PRIVATE_VENDOR_SPECIFIC *key = &priv->sensitiveArea.sensitive.any; TPMI_ALG_HASH name_alg = pub->publicArea.nameAlg; return tpm2_util_calc_unique(name_alg, key, seed, unique); } static bool load_private_RSA_from_key(EVP_PKEY *key, TPM2B_SENSITIVE *priv) { bool result = false; #if OPENSSL_VERSION_NUMBER < 0x30000000L const BIGNUM *p = NULL; /* the private key exponent */ RSA *k = EVP_PKEY_get0_RSA(key); if (!k) { LOG_ERR("Could not retrieve RSA key"); goto out; } RSA_get0_factors(k, &p, NULL); #else BIGNUM *p = NULL; /* the private key exponent */ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_RSA_FACTOR1, &p); if (!rc) { LOG_ERR("Could not read private key"); goto out; } #endif TPMT_SENSITIVE *sa = &priv->sensitiveArea; sa->sensitiveType = TPM2_ALG_RSA; TPM2B_PRIVATE_KEY_RSA *pkr = &sa->sensitive.rsa; unsigned priv_bytes = BN_num_bytes(p); if (priv_bytes > sizeof(pkr->buffer)) { LOG_ERR("Expected prime \"d\" to be less than or equal to %zu," " got: %u", sizeof(pkr->buffer), priv_bytes); goto out; } pkr->size = priv_bytes; int success = BN_bn2bin(p, pkr->buffer); if (!success) { ERR_print_errors_fp(stderr); LOG_ERR("Could not copy private exponent \"d\""); goto out; } result = true; out: #if OPENSSL_VERSION_NUMBER < 0x30000000L /* k,p point to internal structrues and must not be freed after use */ #else BN_free(p); #endif return result; } bool tpm2_openssl_load_public(const char *path, TPMI_ALG_PUBLIC alg, TPM2B_PUBLIC *pub) { FILE *f = fopen(path, "rb"); if (!f) { LOG_ERR("Could not open file \"%s\" error: %s", path, strerror(errno)); return false; } bool result = false; switch (alg) { case TPM2_ALG_RSA: result = load_public_RSA_from_pem(f, path, pub); break; case TPM2_ALG_ECC: result = load_public_ECC_from_pem(f, path, pub); break; /* Skip AES here, as we can only load this one from a private file */ default: LOG_ERR("Unkown public format: 0x%x", alg); } fclose(f); return result; } static bool load_private_ECC_from_key(EVP_PKEY *key, TPM2B_SENSITIVE *priv) { bool result = false; /* * private data */ priv->sensitiveArea.sensitiveType = TPM2_ALG_ECC; TPM2B_ECC_PARAMETER *p = &priv->sensitiveArea.sensitive.ecc; #if OPENSSL_VERSION_NUMBER < 0x30000000L EC_KEY *k = EVP_PKEY_get0_EC_KEY(key); if (!k) { LOG_ERR("Could not retrieve ECC key"); goto out; } const EC_GROUP *group = EC_KEY_get0_group(k); const BIGNUM *b = EC_KEY_get0_private_key(k); unsigned priv_bytes = (EC_GROUP_get_degree(group) + 7) / 8; #else BIGNUM *b = NULL; /* the private key exponent */ int rc = EVP_PKEY_get_bn_param(key, OSSL_PKEY_PARAM_PRIV_KEY, &b); if (!rc) { LOG_ERR("Could not read ECC private key"); goto out; } unsigned priv_bytes = (EVP_PKEY_bits(key) + 7) / 8; #endif if (priv_bytes > sizeof(p->buffer)) { LOG_ERR("Expected ECC private portion to be less than or equal to %zu," " got: %u", sizeof(p->buffer), priv_bytes); goto out; } p->size = BN_bn2binpad(b, p->buffer, priv_bytes); if (p->size != priv_bytes) { goto out; } result = true; out: #if OPENSSL_VERSION_NUMBER < 0x30000000L /* k,b point to internal structrues and must not be freed after use */ #else BN_free(b); #endif return result; } static tpm2_openssl_load_rc load_private_ECC_from_pem(FILE *f, const char *path, const char *passin, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { tpm2_openssl_load_rc rc = lprc_error; char *pass = NULL; bool result = handle_ossl_pass(passin, &pass); if (!result) { return lprc_error; } EVP_PKEY *k = PEM_read_PrivateKey(f, NULL, NULL, (void *) pass); free(pass); if (!k) { ERR_print_errors_fp(stderr); LOG_ERR("Reading PEM file \"%s\" failed", path); return lprc_error; } result = load_private_ECC_from_key(k, priv); if (!result) { rc = lprc_error; goto out; } rc |= lprc_private; result = load_public_ECC_from_key(k, pub); if (!result) { rc = lprc_error; goto out; } rc |= lprc_public; out: EVP_PKEY_free(k); return rc; } static tpm2_openssl_load_rc load_private_RSA_from_pem(FILE *f, const char *path, const char *passin, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { EVP_PKEY *k = NULL; tpm2_openssl_load_rc rc = lprc_error; char *pass = NULL; bool result = handle_ossl_pass(passin, &pass); if (!result) { return lprc_error; } k = PEM_read_PrivateKey(f, NULL, NULL, (void *) pass); free(pass); if (!k) { ERR_print_errors_fp(stderr); LOG_ERR("Reading PEM file \"%s\" failed", path); return lprc_error; } bool loaded_priv = load_private_RSA_from_key(k, priv); if (!loaded_priv) { return lprc_error; } else { rc |= lprc_private; } bool loaded_pub = load_public_RSA_from_key(k, pub); if (!loaded_pub) { goto out; } else { rc |= lprc_public; } out: EVP_PKEY_free(k); return rc; } static tpm2_openssl_load_rc load_private_AES_from_file(FILE *f, const char *path, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { unsigned long file_size = 0; bool result = files_get_file_size(f, &file_size, path); if (!result) { return lprc_error; } result = tpm2_alg_util_is_aes_size_valid(file_size); if (!result) { return lprc_error; } priv->sensitiveArea.sensitiveType = TPM2_ALG_SYMCIPHER; TPM2B_SYM_KEY *s = &priv->sensitiveArea.sensitive.sym; s->size = file_size; result = files_read_bytes(f, s->buffer, s->size); if (!result) { return lprc_error; } result = load_public_AES_from_file(f, path, pub, priv); if (!result) { return lprc_error; } return lprc_private | lprc_public; } static tpm2_openssl_load_rc load_private_KEYEDHASH_from_file(FILE *f, const char *path, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { unsigned long file_size = 0; bool result = files_get_file_size(f, &file_size, path); if (!result) { return lprc_error; } priv->sensitiveArea.sensitiveType = TPM2_ALG_KEYEDHASH; size_t max_size = pub->publicArea.parameters.keyedHashDetail.scheme.scheme == TPM2_ALG_NULL ? KEYEDHASH_MAX_SIZE : HMAC_MAX_SIZE; if (file_size > max_size || file_size == 0) { LOG_ERR("Invalid %s key size, got %lu bytes, expected 1 to 128 bytes", tpm2_alg_util_algtostr( pub->publicArea.parameters.keyedHashDetail.scheme.scheme, tpm2_alg_util_flags_any), file_size); return lprc_error; } TPM2B_SENSITIVE_DATA *b = &priv->sensitiveArea.sensitive.bits; b->size = file_size; result = files_read_bytes(f, b->buffer, b->size); if (!result) { return lprc_error; } /* * calculate the unique and we're done, this is the only thing left for public * so no need for another function. */ TPM2B_DIGEST *unique = &pub->publicArea.unique.keyedHash; TPM2B_DIGEST *seed = &priv->sensitiveArea.seedValue; TPM2B_PRIVATE_VENDOR_SPECIFIC *key = &priv->sensitiveArea.sensitive.any; TPMI_ALG_HASH name_alg = pub->publicArea.nameAlg; result = tpm2_util_calc_unique(name_alg, key, seed, unique); if (!result) { return lprc_error; } return lprc_private | lprc_public; } tpm2_openssl_load_rc tpm2_openssl_load_private(const char *path, const char *passin, const char *object_auth, TPM2B_PUBLIC *template, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv) { FILE *f = fopen(path, "r"); if (!f) { LOG_ERR("Could not open file \"%s\", error: %s", path, strerror(errno)); return 0; } *pub = *template; tpm2_openssl_load_rc rc = lprc_error; switch (template->publicArea.type) { case TPM2_ALG_RSA: rc = load_private_RSA_from_pem(f, path, passin, pub, priv); break; case TPM2_ALG_SYMCIPHER: if (passin) { LOG_ERR("No password can be used for protecting AES key"); rc = lprc_error; } else if (template->publicArea.parameters.asymDetail.symmetric.algorithm != TPM2_ALG_AES) { LOG_ERR("Cannot handle non-aes symmetric objects, got: 0x%x", template->publicArea.parameters.asymDetail.symmetric.algorithm); rc = lprc_error; } else { rc = load_private_AES_from_file(f, path, pub, priv); } break; case TPM2_ALG_HMAC: /* falls-thru */ case TPM2_ALG_KEYEDHASH: if (passin) { LOG_ERR("No password can be used for protecting %s key", TPM2_ALG_HMAC ? "HMAC" : "Keyed Hash"); rc = lprc_error; } else { rc = load_private_KEYEDHASH_from_file(f, path, pub, priv); } break; case TPM2_ALG_ECC: rc = load_private_ECC_from_pem(f, path, passin, pub, priv); break; default: LOG_ERR("Cannot handle algorithm, got: %s", tpm2_alg_util_algtostr(template->publicArea.type, tpm2_alg_util_flags_any)); rc = lprc_error; } fclose(f); if (object_auth) { tpm2_session *tmp; tool_rc tmp_rc = tpm2_auth_util_from_optarg(NULL, object_auth, &tmp, true); if (tmp_rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return false; } const TPM2B_AUTH *auth = tpm2_session_get_auth_value(tmp); priv->sensitiveArea.authValue = *auth; tpm2_session_close(&tmp); } return rc; } bool tpm2_openssl_import_keys( TPM2B_PUBLIC *parent_pub, TPM2B_ENCRYPTED_SECRET *encrypted_seed, const char *object_auth_value, const char *input_key_file, const char *passin, TPM2B_PUBLIC *template, TPM2B_SENSITIVE *out_private, TPM2B_PUBLIC *out_public ) { bool result; /* * The TPM Requires that the name algorithm for the child be less than the name * algorithm of the parent when the parent's scheme is NULL. * * This check can be seen in the simulator at: * - File: CryptUtil.c * - Func: CryptSecretDecrypt() * - Line: 2019 * - Decription: Limits the size of the hash algorithm to less then the parent's name-alg when scheme is NULL. */ UINT16 hash_size = tpm2_alg_util_get_hash_size(template->publicArea.nameAlg); UINT16 parent_hash_size = tpm2_alg_util_get_hash_size( parent_pub->publicArea.nameAlg); if (hash_size > parent_hash_size) { LOG_WARN("Hash selected is larger then parent hash size, coercing to " "parent hash algorithm: %s", tpm2_alg_util_algtostr(parent_pub->publicArea.nameAlg, tpm2_alg_util_flags_hash)); template->publicArea.nameAlg = parent_pub->publicArea.nameAlg; } /* * Generate and encrypt seed, if requested */ if (encrypted_seed) { TPM2B_DIGEST *seed = &out_private->sensitiveArea.seedValue; static const unsigned char label[] = { 'D', 'U', 'P', 'L', 'I', 'C', 'A', 'T', 'E', '\0' }; result = tpm2_identity_util_share_secret_with_public_key(seed, parent_pub, label, sizeof(label), encrypted_seed); if (!result) { LOG_ERR("Failed Seed Encryption\n"); return false; } } /* * Populate all the private and public data fields we can based on the key type and the PEM files read in. */ tpm2_openssl_load_rc status = tpm2_openssl_load_private(input_key_file, passin, object_auth_value, template, out_public, out_private); if (status == lprc_error) { return false; } if (!tpm2_openssl_did_load_public(status)) { LOG_ERR("Did not find public key information in file: \"%s\"", input_key_file); return false; } return true; } tpm2-tools-5.2/lib/tpm2_openssl.h000066400000000000000000000151351412464516500167610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef LIB_TPM2_OPENSSL_H_ #define LIB_TPM2_OPENSSL_H_ #include #include #include #include #include #include #include "pcr.h" #if OPENSSL_VERSION_NUMBER >= 0x10101000L #define EC_POINT_set_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ EC_POINT_set_affine_coordinates(group, tpm_pub_key, bn_x, bn_y, dmy) #define EC_POINT_get_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ EC_POINT_get_affine_coordinates(group, tpm_pub_key, bn_x, bn_y, dmy) #else #define EC_POINT_set_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ EC_POINT_set_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) #define EC_POINT_get_affine_coordinates_tss(group, tpm_pub_key, bn_x, bn_y, dmy) \ EC_POINT_get_affine_coordinates_GFp(group, tpm_pub_key, bn_x, bn_y, dmy) #endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ static inline const char *tpm2_openssl_get_err(void) { return ERR_error_string(ERR_get_error(), NULL); } /** * Get an openssl hash algorithm ID from a tpm hashing algorithm ID. * @param algorithm * The tpm algorithm to get the corresponding openssl version of. * @return * The openssl hash algorithm id. */ int tpm2_openssl_halgid_from_tpmhalg(TPMI_ALG_HASH algorithm); /** * Get an openssl message digest from a tpm hashing algorithm. * @param algorithm * The tpm algorithm to get the corresponding openssl version of. * @return * A pointer to a message digester or NULL on failure. */ const EVP_MD *tpm2_openssl_md_from_tpmhalg(TPMI_ALG_HASH algorithm); /** * Hash a byte buffer. * @param halg * The hashing algorithm to use. * @param buffer * The byte buffer to be hashed. * @param length * The length of the byte buffer to hash. ^ * @param digest ^ * The result of hashing digests with halg. * @return * true on success, false on error. */ bool tpm2_openssl_hash_compute_data(TPMI_ALG_HASH halg, BYTE *buffer, UINT16 length, TPM2B_DIGEST *digest); /** * Hash a list of PCR digests. * @param halg * The hashing algorithm to use. * @param digests * The list of PCR digests to hash. ^ * @param digest ^ * The result of hashing digests with halg. * @return * true on success, false on error. */ bool tpm2_openssl_hash_pcr_values(TPMI_ALG_HASH halg, TPML_DIGEST *digests, TPM2B_DIGEST *digest); /** * Hash a list of PCR digests, supporting multiple banks. * @param halg * The hashing algorithm to use. * @param pcr_select * The list that specifies which PCRs are selected. * @param pcrs * The list of PCR banks, each containing a list of PCR digests to hash. ^ * @param digest ^ * The result of hashing digests with halg. * @return * true on success, false on error. */ bool tpm2_openssl_hash_pcr_banks(TPMI_ALG_HASH hashAlg, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest); /* * Hash a list of PCR digests, supporting multiple banks. * The data in TPML_PCR_SELECTION and tpm2_pcrs is in little endian format. * * @param halg * The hashing algorithm to use. * @param pcr_select * The list that specifies which PCRs are selected. * @param pcrs * The list of PCR banks, each containing a list of PCR digests to hash. ^ * @param digest ^ * The result of hashing digests with halg. * @return * true on success, false on error. */ bool tpm2_openssl_hash_pcr_banks_le(TPMI_ALG_HASH hashAlg, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs, TPM2B_DIGEST *digest); /** * Extend a PCR with a new digest. * @param halg * The hashing algorithm to use. * @param pcr * A buffer with the current value of the PCR, will be updated in place. * @param data * The new digest to be added to the current PCR. * @param length * Length of the new data to be added to the digest. * @return * true on success, false on error. */ bool tpm2_openssl_pcr_extend(TPMI_ALG_HASH halg, BYTE *pcr, const BYTE *data, UINT16 length); typedef enum tpm2_openssl_load_rc tpm2_openssl_load_rc; enum tpm2_openssl_load_rc { lprc_error = 0, /* an error has occurred */ lprc_private = 1 << 0, /* successfully loaded a private portion of object */ lprc_public = 1 << 1, /* successfully loaded a public portion of object */ }; /** * Helper routine for gathering if the loading status included a public * portion of an object. * * @param load_status * The loading status obtained from a call to tpm2_openssl_load_private(). * @return * True if the load status indicates it loaded a public portion of an object, * false otherwise. */ static inline bool tpm2_openssl_did_load_public( tpm2_openssl_load_rc load_status) { return (load_status & lprc_public); } /** * Loads a private portion of a key, and possibly the public portion, as for RSA the public data is in * a private pem file. * * @param path * The path to load from. * @param passin * If the path needs a password to decrypt like a password protected OpenSSL PEM file. * @param object_auth * The auth value to set for the object, may be NULL. * @param template * The public template to use to construct the TPM objects. * @param pub * The public structure to populate. Note that nameAlg must be populated. * @param priv * The sensitive structure to populate. * * @returns * A private object loading status */ tpm2_openssl_load_rc tpm2_openssl_load_private(const char *path, const char *passin, const char *object_auth, TPM2B_PUBLIC *template, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv); /** * Load an OpenSSL private key and configure all of the flags based on * a parent key, policy, attributes, and authorization. */ bool tpm2_openssl_import_keys( TPM2B_PUBLIC *parent_pub, TPM2B_ENCRYPTED_SECRET *encrypted_seed, const char *object_auth_value, const char *input_key_file, const char *passin, TPM2B_PUBLIC *template, TPM2B_SENSITIVE *private, TPM2B_PUBLIC *public ); /** * Loads a public portion of a key from a file. Files can be the raw key, in the case * of symmetric ciphers, or a PEM file. * * @param path * The path to load from. * @param alg * algorithm type to import. * @param pub * The public structure to populate. * @return * True on success, false on failure. */ bool tpm2_openssl_load_public(const char *path, TPMI_ALG_PUBLIC alg, TPM2B_PUBLIC *pub); /** * Maps an ECC curve to an openssl nid value. * @param curve * The curve to map. * @return * -1 on error or a >=0 nid on success. */ int tpm2_ossl_curve_to_nid(TPMI_ECC_CURVE curve); #endif /* LIB_TPM2_OPENSSL_H_ */ tpm2-tools-5.2/lib/tpm2_options.c000066400000000000000000000377651412464516500170010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "log.h" #include "tpm2_options.h" #ifndef VERSION #warning "VERSION Not known at compile time, not embedding..." #define VERSION "UNKNOWN" #endif #define TPM2TOOLS_ENV_TCTI "TPM2TOOLS_TCTI" #define TPM2TOOLS_ENV_ENABLE_ERRATA "TPM2TOOLS_ENABLE_ERRATA" tpm2_options *tpm2_options_new(const char *short_opts, size_t len, const struct option *long_opts, tpm2_option_handler on_opt, tpm2_arg_handler on_arg, uint32_t flags) { tpm2_options *opts = calloc(1, sizeof(*opts) + (sizeof(*long_opts) * len)); if (!opts) { LOG_ERR("oom"); return NULL; } /* * On NULL, just make it a zero length string so we don't have to keep * checking it for NULL. */ if (!short_opts) { short_opts = ""; } opts->short_opts = strdup(short_opts); if (!opts->short_opts) { LOG_ERR("oom"); free(opts); return NULL; } opts->callbacks.on_opt = on_opt; opts->callbacks.on_arg = on_arg; opts->len = len; opts->flags = flags; memcpy(opts->long_opts, long_opts, len * sizeof(*long_opts)); return opts; } bool tpm2_options_cat(tpm2_options **dest, tpm2_options *src) { tpm2_options *d = *dest; /* move the nested char * pointer first */ size_t opts_len = strlen(d->short_opts) + strlen(src->short_opts) + 1; char *tmp_short = realloc(d->short_opts, opts_len); if (!tmp_short) { LOG_ERR("oom"); return false; } strcat(tmp_short, src->short_opts); d->short_opts = tmp_short; /* now move the enclosing structure */ size_t long_opts_len = d->len + src->len; /* +1 for a terminating NULL at the end of options array for getopt_long */ tpm2_options *tmp = realloc(d, sizeof(*d) + ((long_opts_len + 1) * sizeof(d->long_opts[0]))); if (!tmp) { LOG_ERR("oom"); return false; } *dest = d = tmp; d->callbacks.on_arg = src->callbacks.on_arg; d->callbacks.on_opt = src->callbacks.on_opt; d->flags = src->flags; memcpy(&d->long_opts[d->len], src->long_opts, src->len * sizeof(src->long_opts[0])); /* length must be updated post memcpy as we need d->len to be the original offset */ d->len = long_opts_len; /* NULL term for getopt_long */ memset(&d->long_opts[d->len], 0, sizeof(d->long_opts[0])); return true; } void tpm2_options_free(tpm2_options *opts) { if (!opts) { return; } free(opts->short_opts); free(opts); } static bool execute_man(char *prog_name, bool show_errors) { pid_t pid; int status; if ((pid = fork()) < 0) { LOG_ERR("Could not fork process to execute man, error: %s", strerror(errno)); return false; } #define MAX_TOOL_NAME_LEN 64 if (pid == 0) { if (!show_errors) { /* redirect manpager errors to stderr */ int fd = open("/dev/null", O_WRONLY); if (fd < 0) { LOG_ERR("Could not open /dev/null"); return false; } dup2(fd, 2); close(fd); } const char *manpage = basename(prog_name); if (!strcmp(manpage, "tpm2")) { /* * Handle the case where tpm2 is specified without tool-name or help */ execlp("man", "man", "tpm2", NULL); } else if (strncmp(manpage, "tpm2_", strlen("tpm2_"))) { /* * Handle the case where the tool is specified as tpm2< >tool-name */ char man_tool_name[MAX_TOOL_NAME_LEN] = {'t','p','m','2','_'}; strncat(man_tool_name, manpage, strlen(manpage) < (MAX_TOOL_NAME_LEN - strlen("tpm2_")) ? strlen(manpage) : (MAX_TOOL_NAME_LEN - strlen("tpm2_"))); execlp("man", "man", man_tool_name, NULL); } else { /* * Handle the case where the tool is specified as tpm2<_>tool-name */ execlp("man", "man", manpage, NULL); } } else { if (waitpid(pid, &status, 0) == -1) { LOG_ERR("Waiting for child process that executes man failed, error:" " %s", strerror(errno)); return false; } return WEXITSTATUS(status) == 0; } return true; } static void show_version(const char *name) { const char *tcti_default = NULL; TSS2_TCTI_INFO *info = NULL; TSS2_RC rc = Tss2_TctiLdr_GetInfo(NULL, &info); if (rc == TSS2_RC_SUCCESS && info != NULL) { tcti_default = info->name; } printf("tool=\"%s\" version=\"%s\" tctis=\"libtss2-tctildr\" tcti-default=%s\n", name, VERSION, tcti_default); Tss2_TctiLdr_FreeInfo(&info); } void tpm2_print_usage(const char *command, struct tpm2_options *tool_opts) { unsigned int i; bool indent = true; char *command_copy; if (!tool_opts || !command) { return; } command_copy = strdup(command); printf("Usage: %s%s%s\n", basename(command_copy), tool_opts->callbacks.on_opt ? " []" : "", tool_opts->callbacks.on_arg ? " " : ""); free(command_copy); if (tool_opts->callbacks.on_opt) { printf("Where are:\n"); for (i = 0; i < tool_opts->len; i++) { struct option *opt = &tool_opts->long_opts[i]; if (indent) { printf(" "); indent = false; } else { printf(" "); } if (isalpha(opt->val)) { printf("[ -%c | --%s%s]", opt->val, opt->name, opt->has_arg ? "=" : ""); } else { printf("[ --%s%s]", opt->name, opt->has_arg ? "=" : ""); } if ((i + 1) % 4 == 0) { printf("\n"); indent = true; } } if (i % 4 != 0) { printf("\n"); } } } static TSS2_RC tcti_fake_receive (TSS2_TCTI_CONTEXT *tctiContext, size_t *response_size, unsigned char *response_buffer, int32_t timeout) { (void) tctiContext; (void) response_size; (void) response_buffer; (void) timeout; LOG_ERR("Fake tcti's receive invoked. You shouldn't be here!"); return TSS2_TCTI_RC_NOT_IMPLEMENTED; } static void tcti_fake_finalize (TSS2_TCTI_CONTEXT *tctiContext) { (void) tctiContext; } static TSS2_RC tcti_fake_transmit (TSS2_TCTI_CONTEXT *tcti_ctx, size_t size, const uint8_t *cmd_buf) { (void) tcti_ctx; (void) size; (void) cmd_buf; LOG_ERR("Fake tcti's transmit invoked. You shouldn't be here!"); return TSS2_TCTI_RC_NOT_IMPLEMENTED; } tpm2_option_code tpm2_handle_options(int argc, char **argv, tpm2_options *tool_opts, tpm2_option_flags *flags, TSS2_TCTI_CONTEXT **tcti) { /* * Handy way to *try* and find all used options: * grep -rn case\ \'[a-zA-Z]\' | awk '{print $3}' | sed s/\'//g | sed s/\://g | sort | uniq | less */ struct option long_options [] = { { "tcti", required_argument, NULL, 'T' }, { "help", optional_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'V' }, { "quiet", no_argument, NULL, 'Q' }, { "version", no_argument, NULL, 'v' }, { "enable-errata", no_argument, NULL, 'Z' }, }; /* handle any options */ const char* common_short_opts = "T:h::vVQZ"; tpm2_options *opts = tpm2_options_new(common_short_opts, ARRAY_LEN(long_options), long_options, NULL, NULL, 0); if (!opts) { return tpm2_option_code_err; } /* Get the options from the tool */ bool show_help = false; tpm2_option_code rc = tpm2_option_code_continue; bool result = false; if (tool_opts) { result = tpm2_options_cat(&opts, tool_opts); if (!result) { rc = tpm2_option_code_err; goto out; } } /* Parse the options, calling the tool callback if unknown */ const char *tcti_conf_option = NULL; optind = 1; int c; bool manpager = true; bool explicit_manpager = false; while ((c = getopt_long(argc, argv, opts->short_opts, opts->long_opts, NULL)) != -1) { switch (c) { case 'T': if (opts->flags & TPM2_OPTIONS_NO_SAPI) { LOG_ERR("%s: tool doesn't support the TCTI option", argv[0]); rc = tpm2_option_code_err; goto out; } /* only attempt to get options from tcti option string */ tcti_conf_option = optarg; flags->tcti_none = !strcmp(tcti_conf_option, "none"); break; case 'h': show_help = true; /* * argv[0] = "tool name" * argv[1] = "--help=no/man" argv[2] = 0 */ if (argv[optind - 1]) { if (!strcmp(argv[optind - 1], "--help=no-man") || !strcmp(argv[optind - 1], "-h=no-man") || (argc < optind && !strcmp(argv[optind], "no-man"))) { manpager = false; optind++; /* * argv[0] = "tool name" * argv[1] = "--help" argv[2] = "no/man" */ } else if (!strcmp(argv[optind - 1], "--help=man") || !strcmp(argv[optind - 1], "-h=man") || (argc < optind && !strcmp(argv[optind], "man"))) { manpager = true; explicit_manpager = true; optind++; } else { /* * argv[0] = "tool name" * argv[1] = "--help" argv[2] = 0 */ if (optind >= argc && argc == 2) { manpager = false; } else { /* * ERROR */ show_help = false; LOG_ERR("Unknown help argument, got: \"%s\"", argv[optind]); } } } rc = tpm2_option_code_err; goto out; case 'V': flags->verbose = 1; break; case 'Q': flags->quiet = 1; break; case 'v': show_version(argv[0]); rc = tpm2_option_code_stop; goto out; break; case 'Z': flags->enable_errata = 1; break; case '?': rc = tpm2_option_code_err; goto out; default: /* NULL on_opt handler and unknown option specified is an error */ if (!tool_opts || !tool_opts->callbacks.on_opt) { LOG_ERR("Unknown option found: %c", c); rc = tpm2_option_code_err; goto out; } result = tool_opts->callbacks.on_opt(c, optarg); if (!result) { rc = tpm2_option_code_err; goto out; } } } char **tool_args = &argv[optind]; int tool_argc = argc - optind; /* have args and no handler, error condition */ if (tool_argc && (!tool_opts || !tool_opts->callbacks.on_arg)) { LOG_ERR("Got arguments but the tool takes no arguments"); show_help = true; rc = tpm2_option_code_err; goto out; } /* have args and a handler to process */ else if (tool_argc && tool_opts->callbacks.on_arg) { result = tool_opts->callbacks.on_arg(tool_argc, tool_args); if (!result) { rc = tpm2_option_code_err; goto out; } } /* Only init a TCTI if the tool needs it and if the -h/--help option isn't present */ TSS2_RC rc_tcti; if (!show_help) { /* * Cases to handle: * SAPI [0] | NO_SAPI [1] | OPTIONAL_SAPI [2] | FAKE_TCTI [4] */ /* * SAPI */ bool is_sapi = (!tool_opts || !tool_opts->flags); /* * NO_SAPI */ bool is_no_sapi = (tool_opts && tool_opts->flags & TPM2_OPTIONS_NO_SAPI); /* tool doesn't use sapi, skip tcti checks and continue */ if (is_no_sapi) { goto out; } /* * OPTIONAL_SAPI */ bool is_optional_sapi = (tool_opts && tool_opts->flags & TPM2_OPTIONS_OPTIONAL_SAPI); /* * Actions when tcti is "none" */ bool is_tcti_from_env = (!is_no_sapi && tcti_conf_option == 0); if (is_tcti_from_env) { tcti_conf_option = tpm2_util_getenv(TPM2TOOLS_ENV_TCTI); } if (flags->tcti_none && is_sapi) { LOG_ERR("Requested no tcti, but tool requires TCTI."); rc = tpm2_option_code_err; goto out; } /* tool doesn't request a sapi, don't initialize one */ if (flags->tcti_none && is_optional_sapi) { LOG_WARN("Tool optionally uses SAPI. Continuing with tcti=none"); goto none; } if (flags->tcti_none && is_no_sapi) { LOG_WARN("Tool does not use SAPI. Continuing with tcti=none"); goto none; } /* * FAKE_TCTI */ /* tool doesn't request a sapi but instead requires a fake tcti*/ #define TCTI_FAKE_MAGIC 0x09b366943a311b04ULL static const TSS2_TCTI_CONTEXT_COMMON_V1 fake_tcti = { .magic = TCTI_FAKE_MAGIC, .version = 1, .transmit = tcti_fake_transmit, .receive = tcti_fake_receive, .finalize = tcti_fake_finalize }; bool is_optional_fake_tcti = (flags->tcti_none && tool_opts && tool_opts->flags & TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI); if (is_optional_fake_tcti) { LOG_WARN("Tool optionally uses SAPI. Continuing with tcti=fake"); *tcti = (TSS2_TCTI_CONTEXT *)&fake_tcti; goto none; } rc_tcti = Tss2_TctiLdr_Initialize(tcti_conf_option, tcti); if (rc_tcti != TSS2_RC_SUCCESS || !*tcti) { LOG_ERR("Could not load tcti, got: \"%s\"", tcti_conf_option); rc = tpm2_option_code_err; goto out; } /* * no loader requested ie --tcti=none is an error if tool * doesn't indicate an optional SAPI */ if (!flags->enable_errata) { flags->enable_errata = !!tpm2_util_getenv( TPM2TOOLS_ENV_ENABLE_ERRATA); } } none: rc = tpm2_option_code_continue; out: /* * If help output is selected via -h or indicated by an error that help output * is desirable, show it. * * However, 3 conditions are possible: * 1. Try manpager and success -- done, no need to show short help output. * 2. Try manpager and failure -- show short help output. * 3. Do not use manpager -- show short help output. * */ if (show_help) { bool did_manpager = false; if (manpager) { did_manpager = execute_man(argv[0], explicit_manpager); } if (!did_manpager) { tpm2_print_usage(argv[0], tool_opts); } if (tcti_conf_option && strcmp(tcti_conf_option, "none")) { TSS2_TCTI_INFO *info = NULL; rc_tcti = Tss2_TctiLdr_GetInfo(tcti_conf_option, &info); if (rc_tcti == TSS2_RC_SUCCESS && info) { printf("\ntcti-help(%s): %s\n", info->name, info->config_help); } Tss2_TctiLdr_FreeInfo(&info); } rc = tpm2_option_code_stop; } tpm2_options_free(opts); return rc; } tpm2-tools-5.2/lib/tpm2_options.h000066400000000000000000000112571412464516500167720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef OPTIONS_H #define OPTIONS_H #include #include #include #include #include #define TPM2TOOLS_ENV_TCTI "TPM2TOOLS_TCTI" #define TPM2TOOLS_ENV_ENABLE_ERRATA "TPM2TOOLS_ENABLE_ERRATA" typedef union tpm2_option_flags tpm2_option_flags; union tpm2_option_flags { struct { uint8_t verbose :1; uint8_t quiet :1; uint8_t enable_errata :1; uint8_t tcti_none :1; }; uint8_t all; }; /** * Tools may implement this optional interface if they need * to handle options. * @param key * The key of the option, ie short option return value from getopt_long(). * @param value * The getopt_long optarg value. * @return * true on success, false on error. * @note * LOG_INFO and TOOL_OUTPUT will not work correctly during this callback. * This is called after onstart() finishes, but before * onrun() is invoked. * */ typedef bool (*tpm2_option_handler)(char key, char *value); /** * Called after option handling to process arguments, if specified. * @param argc * The number of args in argv. * @param argv * The arguments. * @return * true on success, false otherwise. * @note * LOG_INFO adn TOOL_OUTPUT will not work correctly during this callback. * This is called after onstart() and tpm2_option_handler() (if specified), * but before onrun() is invoked. * */ typedef bool (*tpm2_arg_handler)(int argc, char **argv); /** * TPM2_OPTIONS_* flags change default behavior of the argument parser * * TPM2_OPTIONS_NO_SAPI: * Skip SAPI initialization. Removes the "-T" common option. */ #define TPM2_OPTIONS_NO_SAPI 0x1 #define TPM2_OPTIONS_OPTIONAL_SAPI 0x2 #define TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI 0x4 struct tpm2_options { struct { tpm2_option_handler on_opt; tpm2_arg_handler on_arg; } callbacks; char *short_opts; size_t len; uint32_t flags; struct option long_opts[]; }; typedef struct tpm2_options tpm2_options; /** * The onstart() routine expects a return of NULL or a tpm2_options structure. * This routine initializes said object. * @param short_opts * Any short options you wish to specify to getopt_long. * @param len * The length of the long_opts array. * @param long_opts * Any long options you wish to specify to getopt_long(). * @param on_opt * An option handling callback, which may be null if you don't wish * to handle options. * @param on_arg * An argument handling callback, which may be null if you don't wish * to handle arguments. * @param flags * TPM2_OPTIONS_* bit flags * @return * NULL on failure or an initialized tpm2_options object. */ tpm2_options *tpm2_options_new(const char *short_opts, size_t len, const struct option *long_opts, tpm2_option_handler on_opt, tpm2_arg_handler on_arg, uint32_t flags); /** * Concatenates two tpm2_options objects, with src appended on * dest. The internal callbacks for tpm2_arg_handler and tpm2_option_handler * which were specified during tpm2_options_new() are copied from src to * dest, thus overwriting dest. Short and long options are concatenated. * @param dest * The tpm2_options object to append to. * @param src * The source tpm2_options to append onto dest. * @return * true on success, false otherwise. */ bool tpm2_options_cat(tpm2_options **dest, tpm2_options *src); /** * Free's a tpm2_options created via tpm2_options_new(). * @param opts * The tpm2_options object to deallocate. */ void tpm2_options_free(tpm2_options *opts); typedef enum tpm2_option_code tpm2_option_code; enum tpm2_option_code { tpm2_option_code_continue, tpm2_option_code_stop, tpm2_option_code_err }; /** * Parses the tpm2_tool command line. * * @param argc * The argc from main. * @param argv * The argv from main. * @param tool_opts * The tool options gathered during onstart() lifecycle call. * @param flags * The tpm2_option_flags to set during parsing. * @param tcti * The tcti initialized from the tcti options. * @return * A tpm option code indicating if an error, further processing * or an immediate exit is desired. * @note * Used by tpm2_tool, and likely should only be used there. * */ tpm2_option_code tpm2_handle_options(int argc, char **argv, tpm2_options *tool_opts, tpm2_option_flags *flags, TSS2_TCTI_CONTEXT **tcti); /** * Print usage summary for a given tpm2 tool. * * @param command * The command to print its usage summary text. * @param tool_opts * The tpm2_options array that contains the tool options to print as a summary. */ void tpm2_print_usage(const char *command, struct tpm2_options *tool_opts); #endif /* OPTIONS_H */ tpm2-tools-5.2/lib/tpm2_policy.c000066400000000000000000000526771412464516500166040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_openssl.h" #include "tpm2_policy.h" #include "tpm2_tool.h" #include "tpm2_util.h" static bool evaluate_populate_pcr_digests(TPML_PCR_SELECTION *pcr_selections, const char *raw_pcrs_file, TPML_DIGEST *pcr_values) { unsigned expected_pcr_input_file_size = 0; unsigned dgst_cnt = 0; //Iterating the number of pcr banks selected UINT32 i; for (i = 0; i < pcr_selections->count; i++) { UINT8 total_indices_for_this_alg = 0; //Looping to check total pcr select bits in the pcr-select-octets for a bank UINT32 j; for (j = 0; j < pcr_selections->pcrSelections[i].sizeofSelect; j++) { UINT8 group_val = pcr_selections->pcrSelections[i].pcrSelect[j]; total_indices_for_this_alg += tpm2_util_pop_count(group_val); } if (pcr_values->count + total_indices_for_this_alg> ARRAY_LEN(pcr_values->digests)) { LOG_ERR("Number of PCR is limited to %zu", ARRAY_LEN(pcr_values->digests)); return false; } //digest size returned per the hashAlg type unsigned dgst_size = tpm2_alg_util_get_hash_size( pcr_selections->pcrSelections[i].hash); if (!dgst_size) { return false; } expected_pcr_input_file_size += (total_indices_for_this_alg * dgst_size); //Cumulative total of all the pcr indices across banks selected in setlist pcr_values->count += total_indices_for_this_alg; /* * Populating the digest sizes in the PCR digest list per algorithm bank * Once iterated through all banks, creates an file offsets map for all pcr indices */ UINT8 k; for (k = 0; k < total_indices_for_this_alg; k++) { pcr_values->digests[dgst_cnt].size = dgst_size; dgst_cnt++; } } //Check if the input pcrs file size is the same size as the pcr selection setlist if (raw_pcrs_file) { unsigned long filesize = 0; bool result = files_get_file_size_path(raw_pcrs_file, &filesize); if (!result) { LOG_ERR("Could not retrieve raw_pcrs_file size"); return false; } if (filesize != expected_pcr_input_file_size) { LOG_ERR("pcr-input-file filesize does not match pcr set-list"); return false; } } return true; } tool_rc tpm2_policy_build_pcr(ESYS_CONTEXT *ectx, tpm2_session *policy_session, const char *raw_pcrs_file, TPML_PCR_SELECTION *pcr_selections, TPM2B_DIGEST *raw_pcr_digest) { TPML_DIGEST pcr_values = { .count = 0 }; if (!pcr_selections->count) { LOG_ERR("No pcr selection data specified!"); return tool_rc_general_error; } TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer); TPMI_ALG_HASH auth_hash = tpm2_session_get_authhash(policy_session); ESYS_TR handle = tpm2_session_get_handle(policy_session); /* * If digest of all PCRs is directly given, handle it here. */ if (raw_pcr_digest && raw_pcr_digest->size != tpm2_alg_util_get_hash_size(auth_hash)) { LOG_ERR("Specified PCR digest length not suitable with the policy session digest"); return tool_rc_general_error; } // Call the PolicyPCR command if (raw_pcr_digest) { return tpm2_policy_pcr(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, raw_pcr_digest, pcr_selections); } bool result = evaluate_populate_pcr_digests(pcr_selections, raw_pcrs_file, &pcr_values); if (!result) { return tool_rc_general_error; } //If PCR input for policy is from raw pcrs file if (raw_pcrs_file) { FILE *fp = fopen(raw_pcrs_file, "rb"); if (fp == NULL) { LOG_ERR("Cannot open pcr-input-file %s", raw_pcrs_file); return tool_rc_general_error; } // Bank hashAlg values dictates the order of the list of digests unsigned i; for (i = 0; i < pcr_values.count; i++) { size_t sz = fread(&pcr_values.digests[i].buffer, 1, pcr_values.digests[i].size, fp); if (sz != pcr_values.digests[i].size) { const char *msg = ferror(fp) ? strerror(errno) : "end of file reached"; LOG_ERR("Reading from file \"%s\" failed: %s", raw_pcrs_file, msg); fclose(fp); return tool_rc_general_error; } } fclose(fp); } else { UINT32 pcr_update_counter; TPML_DIGEST *pcr_val = NULL; // Read PCRs tool_rc rc = tpm2_pcr_read(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, pcr_selections, &pcr_update_counter, NULL, &pcr_val); if (rc != tool_rc_success) { return rc; } UINT32 i; pcr_val->count = pcr_values.count; for (i = 0; i < pcr_val->count; i++) { memcpy(pcr_values.digests[i].buffer, pcr_val->digests[i].buffer, pcr_val->digests[i].size); pcr_values.digests[i].size = pcr_val->digests[i].size; } free(pcr_val); } // Calculate hashes result = tpm2_openssl_hash_pcr_values(auth_hash, &pcr_values, &pcr_digest); if (!result) { LOG_ERR("Could not hash pcr values"); return tool_rc_general_error; } // Call the PolicyPCR command return tpm2_policy_pcr(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &pcr_digest, pcr_selections); } tool_rc tpm2_policy_build_policyauthorize(ESYS_CONTEXT *ectx, tpm2_session *policy_session, const char *policy_digest_path, const char *qualifying_data, const char *verifying_pubkey_name_path, const char *ticket_path) { bool result = true; TPM2B_DIGEST approved_policy = { .size = 0 }; if (policy_digest_path) { approved_policy.size = sizeof(TPMU_HA); result = files_load_bytes_from_path(policy_digest_path, approved_policy.buffer, &approved_policy.size); } if (!result) { return tool_rc_general_error; } /* * Qualifier data is optional. If not specified default to 0 */ TPM2B_NONCE policy_qualifier = { .size = 0 }; if (qualifying_data) { policy_qualifier.size = sizeof(policy_qualifier.buffer); result = tpm2_util_bin_from_hex_or_file(qualifying_data, &policy_qualifier.size, policy_qualifier.buffer); if (!result) { return tool_rc_general_error; } } unsigned long file_size = 0; result = files_get_file_size_path(verifying_pubkey_name_path, &file_size); if (!result) { return tool_rc_general_error; } if (!file_size) { LOG_ERR("Verifying public key name file \"%s\", cannot be empty", verifying_pubkey_name_path); return tool_rc_general_error; } TPM2B_NAME key_sign = { .size = (uint16_t) file_size }; result = files_load_bytes_from_path(verifying_pubkey_name_path, key_sign.name, &key_sign.size); if (!result) { return tool_rc_general_error; } TPMT_TK_VERIFIED check_ticket = { .tag = TPM2_ST_VERIFIED, .hierarchy = TPM2_RH_OWNER, .digest = { 0 } }; result = tpm2_session_is_trial(policy_session); if (!result) { result = files_load_ticket(ticket_path, &check_ticket); if (!result) { LOG_ERR("Could not load verification ticket file"); return tool_rc_general_error; } } ESYS_TR sess_handle = tpm2_session_get_handle(policy_session); return tpm2_policy_authorize(ectx, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &approved_policy, &policy_qualifier, &key_sign, &check_ticket); } tool_rc tpm2_policy_build_policyor(ESYS_CONTEXT *ectx, tpm2_session *policy_session, TPML_DIGEST *policy_list) { ESYS_TR sess_handle = tpm2_session_get_handle(policy_session); return tpm2_policy_or(ectx, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, policy_list); } tool_rc tpm2_policy_build_policypassword(ESYS_CONTEXT *ectx, tpm2_session *session) { ESYS_TR policy_session_handle = tpm2_session_get_handle(session); return tpm2_policy_password(ectx, policy_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE); } tool_rc tpm2_policy_build_policynamehash(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *name_hash) { ESYS_TR policy_session_handle = tpm2_session_get_handle(session); return tpm2_policy_namehash(ectx, policy_session_handle, name_hash); } tool_rc tpm2_policy_build_policytemplate(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *template_hash) { ESYS_TR policy_session_handle = tpm2_session_get_handle(session); return tpm2_policy_template(ectx, policy_session_handle, template_hash); } tool_rc tpm2_policy_build_policycphash(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *cphash) { ESYS_TR policy_session_handle = tpm2_session_get_handle(session); return tpm2_policy_cphash(ectx, policy_session_handle, cphash); } tool_rc tpm2_policy_build_policyauthvalue(ESYS_CONTEXT *ectx, tpm2_session *session) { ESYS_TR policy_session_handle = tpm2_session_get_handle(session); return tpm2_policy_authvalue(ectx, policy_session_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE); } tool_rc tpm2_policy_build_policysecret(ESYS_CONTEXT *ectx, tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj, INT32 expiration, TPMT_TK_AUTH **policy_ticket, TPM2B_TIMEOUT **timeout, bool is_nonce_tpm, const char *policy_qualifier_data, TPM2B_DIGEST *cp_hash) { /* * Qualifier data is optional. If not specified default to 0 */ TPM2B_NONCE policy_qualifier = TPM2B_EMPTY_INIT; if (policy_qualifier_data) { policy_qualifier.size = sizeof(policy_qualifier.buffer); bool result = tpm2_util_bin_from_hex_or_file(policy_qualifier_data, &policy_qualifier.size, policy_qualifier.buffer); if (!result) { return tool_rc_general_error; } } ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session); TPM2B_NONCE *nonce_tpm = NULL; tool_rc rc = tool_rc_success; if (is_nonce_tpm) { rc = tpm2_sess_get_noncetpm(ectx, policy_session_handle, &nonce_tpm); if (rc != tool_rc_success) { goto tpm2_policy_build_policysecret_out; } } rc = tpm2_policy_secret(ectx, auth_entity_obj, policy_session_handle, expiration, policy_ticket, timeout, nonce_tpm, &policy_qualifier, cp_hash); tpm2_policy_build_policysecret_out: Esys_Free(nonce_tpm); return rc; } tool_rc tpm2_policy_build_policyticket(ESYS_CONTEXT *ectx, tpm2_session *policy_session, char *policy_timeout_path, const char *qualifier_data, char *policy_ticket_path, const char *auth_name_path) { unsigned long file_size = 0; bool result = files_get_file_size_path(policy_timeout_path, &file_size); if (!result) { return tool_rc_general_error; } TPM2B_TIMEOUT policy_timeout = { .size = (uint16_t) file_size }; if (policy_timeout.size) { result = files_load_bytes_from_path(policy_timeout_path, policy_timeout.buffer, &policy_timeout.size); if (!result) { return tool_rc_general_error; } } result = files_get_file_size_path(auth_name_path, &file_size); if (!result) { return tool_rc_general_error; } TPM2B_NAME auth_name = { .size = (uint16_t) file_size }; if (auth_name.size) { result = files_load_bytes_from_path(auth_name_path, auth_name.name, &auth_name.size); if (!result) { return tool_rc_general_error; } } TPM2B_NONCE policyref = TPM2B_EMPTY_INIT; if (qualifier_data) { policyref.size = sizeof(policyref.buffer); result = tpm2_util_bin_from_hex_or_file(qualifier_data, &policyref.size, policyref.buffer); if (!result) { return tool_rc_general_error; } } TPMT_TK_AUTH ticket = { 0 }; result = files_load_authorization_ticket(policy_ticket_path, &ticket); if (!result) { LOG_ERR("Failed loading authorization ticket."); return tool_rc_general_error; } ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session); return tpm2_policy_ticket(ectx, policy_session_handle, &policy_timeout, &policyref, &auth_name, &ticket); return tool_rc_success; } tool_rc tpm2_policy_build_policysigned(ESYS_CONTEXT *ectx, tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj, TPMT_SIGNATURE *signature, INT32 expiration, TPM2B_TIMEOUT **timeout, TPMT_TK_AUTH **policy_ticket, const char *policy_qualifier_data, bool is_nonce_tpm, const char *raw_data_path, const char *cphash_path) { bool result = true; /* * Qualifier data is optional. If not specified default to 0 */ TPM2B_NONCE policy_qualifier = TPM2B_EMPTY_INIT; if (policy_qualifier_data) { policy_qualifier.size = sizeof(policy_qualifier.buffer); result = tpm2_util_bin_from_hex_or_file(policy_qualifier_data, &policy_qualifier.size, policy_qualifier.buffer); if (!result) { return tool_rc_general_error; } } /* * CpHashA (digest of command parameters for approved command) optional. * If not specified default to NULL */ TPM2B_DIGEST cphash = TPM2B_EMPTY_INIT; if (cphash_path) { bool result = files_load_digest(cphash_path, &cphash); if (!result) { return tool_rc_general_error; } } ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session); TPM2B_NONCE *nonce_tpm = NULL; tool_rc rc = tool_rc_success; if (is_nonce_tpm) { rc = tpm2_sess_get_noncetpm(ectx, policy_session_handle, &nonce_tpm); if (rc != tool_rc_success) { goto tpm2_policy_build_policysigned_out; } } /* * TPM-Rev-2.0-Part-3-Commands-01.38.pdf * aHash ≔ HauthAlg(nonceTPM || expiration || cpHashA || policyRef) */ if (raw_data_path) { uint16_t raw_data_len = (nonce_tpm ? nonce_tpm->size : 0) + sizeof(INT32) + cphash.size + policy_qualifier.size; uint8_t *raw_data = malloc(raw_data_len); if (!raw_data) { LOG_ERR("oom"); rc = tool_rc_general_error; goto tpm2_policy_build_policysigned_out; } /* nonceTPM */ uint16_t offset = 0; if (nonce_tpm) { memcpy(raw_data, nonce_tpm->buffer, nonce_tpm->size); offset += nonce_tpm->size; } /* expiration */ UINT32 endswap_data = tpm2_util_endian_swap_32(expiration); memcpy(raw_data + offset, (UINT8 *)&endswap_data, sizeof(INT32)); offset += sizeof(INT32); /* cpHash */ if (cphash_path) { memcpy(raw_data + offset, cphash.buffer, cphash.size); offset += cphash.size; } /* policyRef */ memcpy(raw_data + offset, policy_qualifier.buffer, policy_qualifier.size); bool result = files_save_bytes_to_file(raw_data_path, raw_data, raw_data_len); free(raw_data); if (!result) { rc = tool_rc_general_error; } /* * We return since we only need to generate the raw signing data */ goto tpm2_policy_build_policysigned_out; } rc = tpm2_policy_signed(ectx, auth_entity_obj, policy_session_handle, signature, expiration, timeout, policy_ticket, &policy_qualifier, nonce_tpm, &cphash); tpm2_policy_build_policysigned_out: Esys_Free(nonce_tpm); return rc; } tool_rc tpm2_policy_get_digest(ESYS_CONTEXT *ectx, tpm2_session *session, TPM2B_DIGEST **policy_digest) { ESYS_TR handle = tpm2_session_get_handle(session); return tpm2_policy_getdigest(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, policy_digest); } tool_rc tpm2_policy_build_policycommandcode(ESYS_CONTEXT *ectx, tpm2_session *session, uint32_t command_code) { ESYS_TR handle = tpm2_session_get_handle(session); return tpm2_policy_command_code(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, command_code); } tool_rc tpm2_policy_build_policynvwritten(ESYS_CONTEXT *ectx, tpm2_session *session, TPMI_YES_NO written_set) { ESYS_TR handle = tpm2_session_get_handle(session); return tpm2_policy_nv_written(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, written_set); } tool_rc tpm2_policy_build_policylocality(ESYS_CONTEXT *ectx, tpm2_session *session, TPMA_LOCALITY locality) { ESYS_TR handle = tpm2_session_get_handle(session); return tpm2_policy_locality(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, locality); } tool_rc tpm2_policy_build_policyduplicationselect(ESYS_CONTEXT *ectx, tpm2_session *session, const char *obj_name_path, const char *new_parent_name_path, TPMI_YES_NO is_include_obj) { TPM2B_NAME obj_name; bool result = true; if (obj_name_path) { obj_name.size = sizeof(obj_name.name); result = files_load_bytes_from_path(obj_name_path, obj_name.name, &obj_name.size); } else { obj_name.size = 0; } if (!result) { LOG_ERR("Failed to load duplicable object name."); return tool_rc_general_error; } TPM2B_NAME new_parent_name = { .size = sizeof(new_parent_name.name) }; result = files_load_bytes_from_path(new_parent_name_path, new_parent_name.name, &new_parent_name.size); if (!result) { return tool_rc_general_error; } ESYS_TR handle = tpm2_session_get_handle(session); return tpm2_policy_duplication_select(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &obj_name, &new_parent_name, is_include_obj); } static bool tpm2_policy_populate_digest_list(char *buf, TPML_DIGEST *policy_list, TPMI_ALG_HASH hash) { uint8_t hash_len = tpm2_alg_util_get_hash_size(hash); if (!hash_len) { return false; } unsigned long file_size; bool retval = files_get_file_size_path(buf, &file_size); if (!retval) { return false; } if (file_size != hash_len) { return false; } policy_list->digests[policy_list->count].size = hash_len; /* All policy digests are expected to be of same hash len */ if (policy_list->count > 0 && policy_list->digests[policy_list->count].size != policy_list->digests[policy_list->count - 1].size) { return false; } uint16_t policy_digest_size = hash_len; retval = files_load_bytes_from_path(buf, policy_list->digests[policy_list->count].buffer, &policy_digest_size); if (!retval) { return false; } policy_list->count++; return true; } bool tpm2_policy_parse_policy_list(char *str, TPML_DIGEST *policy_list) { char *str1; char *str2; char *token; char *subtoken; char *saveptr1; char *saveptr2; const char *delimiter1 = ":"; const char *delimiter2 = ","; unsigned int j; bool retval; TPMI_ALG_HASH hash = TPM2_ALG_ERROR; for (j = 1, str1 = str;; j++, str1 = NULL) { token = strtok_r(str1, delimiter1, &saveptr1); if (token == NULL) { break; } for (str2 = token;; str2 = NULL) { subtoken = strtok_r(str2, delimiter2, &saveptr2); if (subtoken == NULL) { break; } //Expecting one policy digest of same hash alg type for all policies if (j == 1) { hash = tpm2_alg_util_from_optarg(subtoken, tpm2_alg_util_flags_hash); if (hash == TPM2_ALG_ERROR) { LOG_ERR("Invalid/ Unspecified policy digest algorithm."); return false; } } //Multiple valid policy files if (j > 1) { retval = tpm2_policy_populate_digest_list(subtoken, policy_list, hash); if (!retval) { return false; } } } } return true; } tool_rc tpm2_policy_tool_finish(ESYS_CONTEXT *ectx, tpm2_session *session, const char *save_path) { TPM2B_DIGEST *policy_digest = NULL; tool_rc rc = tpm2_policy_get_digest(ectx, session, &policy_digest); if (rc != tool_rc_success) { LOG_ERR("Could not build tpm policy"); return rc; } tpm2_util_hexdump(policy_digest->buffer, policy_digest->size); tpm2_tool_output("\n"); rc = tool_rc_general_error; if (save_path) { bool result = files_save_bytes_to_file(save_path, policy_digest->buffer, policy_digest->size); if (!result) { LOG_ERR("Failed to save policy digest into file \"%s\"", save_path); goto error; } } rc = tool_rc_success; error: free(policy_digest); return rc; } tpm2-tools-5.2/lib/tpm2_policy.h000066400000000000000000000246601412464516500166000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TPM2_POLICY_H_ #define TPM2_POLICY_H_ #include #include #include "object.h" #include "tpm2_session.h" /** * Build a PCR policy via PolicyPCR. * @param context * The Enhanced System API (ESAPI) context. * @param policy_session * A session started with tpm2_session_new(). * @param raw_pcrs_file * The a file output from tpm2_pcrread -o option. Optional, can be NULL. * If NULL, the PCR values are read via the pcr_selection value. * @param pcr_selections * The pcr selections to use when building the pcr policy. It follows the PCR selection * specifications in the man page for tpm2_listpcrs. If using a raw_pcrs_file, this spec * must be the same as supplied to tpm2_listpcrs. * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_pcr(ESYS_CONTEXT *context, tpm2_session *policy_session, const char *raw_pcrs_file, TPML_PCR_SELECTION *pcr_selections, TPM2B_DIGEST *raw_pcr_digest); /** * Enables a signing authority to authorize policies * @param ectx * The Enhanced system api context * @param policy_session * The policy session that has the policy digest to be authorized * @param policy_digest_path * The policy digest file that needs to be authorized by signing authority * @param policy_qualifier * The policy qualifier data that concatenates with approved policies. Can be * either a path to a file or a hex string. * @param verifying_pubkey_name_path * The name of the public key that verifies the signature of the signer * @param ticket_path * The verification ticket generated when TPM verifies the signature * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policyauthorize(ESYS_CONTEXT *ectx, tpm2_session *policy_session, const char *policy_digest_path, const char *policy_qualifier, const char *verifying_pubkey_name_path, const char *ticket_path); /** * Compounds policies in an OR fashion * * @param ectx * The Enhanced system api context * @param policy_session * The policy session into which the policy digest is extended into * @param policy_list * The list of policy policy digests * * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policyor(ESYS_CONTEXT *ectx, tpm2_session *policy_session, TPML_DIGEST *policy_list); /** * Evaluates an authorization for specific named objects. * * @param ectx * The Enhanced system api context * @param session * The policy session into which the policy digest is extended into * @param name_hash * The name hash * * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policynamehash(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *name_hash); /** * Evaluates an authorization for object's public template data digest. * * @param ectx * The Enhanced system api context * @param session * The policy session into which the policy digest is extended into * @param template_hash * The public template hash * * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policytemplate(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *template_hash); /** * Evaluates an authorization for object's command parameter digest. * * @param ectx * The Enhanced system api context * @param session * The policy session into which the policy digest is extended into * @param cphash * The command parameter hash * * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policycphash(ESYS_CONTEXT *ectx, tpm2_session *session, const TPM2B_DIGEST *cphash); /** * Enables secret (password/hmac) based authorization to a policy. * * @param ectx * The Enhanced system api (ESAPI) context * @param policy_session into which the policy digest is extended into * The policy session * @param[in] secret_session * The secret authentication data to update the policy session with. * Must be a password session. * @param[in] handle * The handle-id of the authentication object * * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policysecret(ESYS_CONTEXT *ectx, tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj, INT32 expiration, TPMT_TK_AUTH **policy_ticket, TPM2B_TIMEOUT **timeout, bool is_nonce_tpm, const char *policy_qualifier_path, TPM2B_DIGEST *cp_hash); /** * Retrieves the policy digest for a session via PolicyGetDigest. * @param context * The Enhanced System API (ESAPI) context. * @param session * The session whose digest to query. * @param policy_digest * The retrieved digest, only valid on true returns. * @return * tool_rc indicating status. */ tool_rc tpm2_policy_get_digest(ESYS_CONTEXT *context, tpm2_session *session, TPM2B_DIGEST **policy_digest); /** * Enables a policy that requires the object's authentication passphrase be * provided. * @param ectx * The Enhanced system api (ESAPI_) context. * @param session * The policy session which is extended with PolicyPassword command code * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policypassword(ESYS_CONTEXT *ectx, tpm2_session *session); /** * Enables a policy that requires the object's authvalue be provided. * The authvalue can be transmitted as an HMAC * @param ectx * The Enhanced system api (ESAPI_) context. * @param session * The policy session which is extended with PolicyAuthValue command code * @return * tool_rc indicating status. */ tool_rc tpm2_policy_build_policyauthvalue(ESYS_CONTEXT *ectx, tpm2_session *session); /** * Enables a policy authorization by virtue of verifying a signature on optional * TPM2 parameters data - nonceTPM, cphashA, policyRef, expiration * @param ectx * The Enhanced system api (ESAPI) context * @param session * The policy session which is extended with PolicySigned command code * @param auth_entity_obj * The loaded TPM2 key object public portion used for signature verification * @param signature * The signature of the optional TPM2 parameters */ tool_rc tpm2_policy_build_policysigned(ESYS_CONTEXT *ectx, tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj, TPMT_SIGNATURE *signature, INT32 expiration, TPM2B_TIMEOUT **timeout, TPMT_TK_AUTH **policy_ticket, const char *policy_qualifier_path, bool is_nonce_tpm, const char *raw_data_path, const char *cphash_path); /** * PolicyTicket assertion enables proxy authentication for either PolicySecret * or PolicySigned once the specific policy is validated. * * @param ectx * The Enhanced system api (ESAPI) context * @param session * The policy session which is being extended * @param policy_timeout_path * The file containing the timeout data generated PolicySigned/ PolicySecret * @param qualifier_data_path * The file containing the qualifier data or policyRef * @param policy_ticket_path * The file containing the auth ticket * @param auth_name_file * The auth name file containing the name of the auth object * * @return { description_of_the_return_value } */ tool_rc tpm2_policy_build_policyticket(ESYS_CONTEXT *ectx, tpm2_session *policy_session, char *policy_timeout_path, const char *qualifier_data_path, char *policy_ticket_path, const char *auth_name_file); /** * Parses the policy digest algorithm for the list of policies specified * * @param str * The string specifying the policy digest algorithm and list of policies * @param policy_list * The policy list structure that records all the policies from policy list * @return * true on success, false otherwise. */ bool tpm2_policy_parse_policy_list(char *str, TPML_DIGEST *policy_list); /** * Policy to restrict tpm object authorization to specific commands * * @param ectx * The Enhanced system api (ESAPI_) context. * @param policy_session * The policy session into which the policy digest is extended into * @param command_code * The command code of the command authorized to use the object * @return * A tool_rc indicating status. */ tool_rc tpm2_policy_build_policycommandcode(ESYS_CONTEXT *ectx, tpm2_session *session, uint32_t command_code); /** * Policy to restrict authorization to written state of the NV Index * * @param ectx * The Enhanced system api (ESAPI_) context. * @param policy_session * The policy session into which the policy digest is extended into * @param written_set * SET/ CLEAR TPMI_YES_NO value of the expected written state of NV index * @return * A tool_rc indicating status. */ tool_rc tpm2_policy_build_policynvwritten(ESYS_CONTEXT *ectx, tpm2_session *session, TPMI_YES_NO written_set); /** * Policy to restrict tpm object authorization to specific locality * * @param ectx * The Enhanced system api (ESAPI_) context. * @param policy_session * The policy session into which the policy digest is extended into * @param locality * The locality of the command authorized to use the object * @return * A tool_rc indicating status. */ tool_rc tpm2_policy_build_policylocality(ESYS_CONTEXT *ectx, tpm2_session *session, TPMA_LOCALITY locality); /** * Policy to restrict tpm object authorization to specific duplication target * * @param ectx * The Enhanced system api (ESAPI_) context. * @param policy_session * The policy session into which the policy digest is extended into * @param obj_name_path * The name of the tpm object to be duplicated * @param new_parent_name_path * The name of the new parent to which the object is duplicated * @param is_include_obj * the flag indicating whether object name is included in policyDigest * @return * A tool_rc indicating status. */ tool_rc tpm2_policy_build_policyduplicationselect(ESYS_CONTEXT *ectx, tpm2_session *session, const char *obj_name_path, const char *new_parent_name_path, TPMI_YES_NO is_include_obj); /** * Policy tools need to: * - get the policy digest * - print the policy digest * - optionally save the digest to a file * This routine serves a common helper so all policy tools * behave in the same way. * @param ectx * The Enhanced system api (ESAPI_) context. * @param session * The policy session to get the digest of. * @param save_path * The path to optionally save the digest too. * @return * A tool_rc indicating status. */ tool_rc tpm2_policy_tool_finish(ESYS_CONTEXT *ectx, tpm2_session *session, const char *save_path); #endif /* TPM2_POLICY_H_ */ tpm2-tools-5.2/lib/tpm2_session.c000066400000000000000000000250461412464516500167560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_session.h" struct tpm2_session_data { ESYS_TR key; ESYS_TR bind; TPM2_SE session_type; TPMT_SYM_DEF symmetric; TPMI_ALG_HASH auth_hash; TPM2B_NONCE nonce_caller; TPMA_SESSION attrs; TPM2B_AUTH auth_data; const char *path; }; struct tpm2_session { tpm2_session_data* input; struct { ESYS_TR session_handle; } output; struct { char *path; ESYS_CONTEXT *ectx; bool is_final; } internal; }; tpm2_session_data *tpm2_session_data_new(TPM2_SE type) { tpm2_session_data * d = calloc(1, sizeof(tpm2_session_data)); if (d) { d->symmetric.algorithm = TPM2_ALG_NULL; d->key = ESYS_TR_NONE; d->bind = ESYS_TR_NONE; d->session_type = type; d->auth_hash = TPM2_ALG_SHA256; } return d; } void tpm2_session_set_key(tpm2_session_data *data, ESYS_TR key) { data->key = key; } void tpm2_session_set_attrs(tpm2_session_data *data, TPMA_SESSION attrs) { data->attrs = attrs; } void tpm2_session_set_auth_value(tpm2_session *session, TPM2B_AUTH *auth) { if (auth == NULL) { session->input->auth_data.size = 0; memset(session->input->auth_data.buffer, 0xBA, sizeof(session->input->auth_data.buffer)); } else { memcpy(&session->input->auth_data, auth, sizeof(*auth)); } } void tpm2_session_set_nonce_caller(tpm2_session_data *data, TPM2B_NONCE *nonce) { data->nonce_caller = *nonce; } void tpm2_session_set_bind(tpm2_session_data *data, ESYS_TR bind) { data->bind = bind; } void tpm2_session_set_type(tpm2_session_data *data, TPM2_SE type) { data->session_type = type; } void tpm2_session_set_symmetric(tpm2_session_data *data, TPMT_SYM_DEF *symmetric) { data->symmetric = *symmetric; } void tpm2_session_set_authhash(tpm2_session_data *data, TPMI_ALG_HASH auth_hash) { data->auth_hash = auth_hash; } void tpm2_session_set_path(tpm2_session_data *data, const char *path) { data->path = path; } TPMI_ALG_HASH tpm2_session_get_authhash(tpm2_session *session) { return session->input->auth_hash; } ESYS_TR tpm2_session_get_handle(tpm2_session *session) { return session->output.session_handle; } TPM2_SE tpm2_session_get_type(tpm2_session *session) { return session->input->session_type; } const TPM2B_AUTH *tpm2_session_get_auth_value(tpm2_session *session) { return &session->input->auth_data; } // // This is a wrapper function around the StartAuthSession command. // It performs the command, calculates the session key, and updates a // SESSION structure. // static tool_rc start_auth_session(tpm2_session *session) { tpm2_session_data *d = session->input; TPM2B_NONCE *nonce = session->input->nonce_caller.size > 0 ? &session->input->nonce_caller : NULL; tool_rc rc = tpm2_start_auth_session(session->internal.ectx, d->key, d->bind, nonce, d->session_type, &d->symmetric, d->auth_hash, &session->output.session_handle); if (rc != tool_rc_success) { return rc; } if (d->attrs) { rc = tpm2_sess_set_attributes(session->internal.ectx, session->output.session_handle, d->attrs, 0xff); if (rc != tool_rc_success) { tool_rc tmp_rc = tpm2_flush_context(session->internal.ectx, session->output.session_handle); UNUSED(tmp_rc); return rc; } } return tool_rc_success; } static void tpm2_session_free(tpm2_session **session) { tpm2_session *s = *session; if (s) { free(s->input); if (s->internal.path) { free(s->internal.path); } free(s); *session = NULL; } } tool_rc tpm2_session_open(ESYS_CONTEXT *context, tpm2_session_data *data, tpm2_session **session) { tpm2_session *s = calloc(1, sizeof(tpm2_session)); if (!s) { free(data); LOG_ERR("oom"); return tool_rc_general_error; } if (data->path) { s->internal.path = strdup(data->path); if (!s->internal.path) { LOG_ERR("oom"); tpm2_session_free(&s); return tool_rc_general_error; } } s->input = data; s->internal.ectx = context; if (!context) { s->output.session_handle = ESYS_TR_PASSWORD; *session = s; return tool_rc_success; } tool_rc rc = start_auth_session(s); if (rc != tool_rc_success) { tpm2_session_free(&s); return rc; } *session = s; return tool_rc_success; } /* SESSION_VERSION 1 was used prior to the switch to ESAPI. As the types of * several of the tpm2_session_data object members have changed the version is * bumped. */ #define SESSION_VERSION 2 /* * Checks that two types are equal in size. * * It works by leveraging the fact that C does not allow negative array sizes. * If the sizes are equal, the boolean equality operator will return 1, thus * a subtraction of 1 yields 0, which is a legal array size in C. In the false * case (ie sizes not equal), 0 - 1 is -1, which will cause the compiler to * complain. */ #define COMPILE_ASSERT_SIZE(a, b) \ typedef char WRONG_SIZE_##a[(sizeof(a) == sizeof(b)) - 1] // We check that the TSS library does not change sizes unbeknownst to us. COMPILE_ASSERT_SIZE(ESYS_TR, UINT32); COMPILE_ASSERT_SIZE(TPMI_ALG_HASH, UINT16); COMPILE_ASSERT_SIZE(TPM2_SE, UINT8); tool_rc tpm2_session_restore(ESYS_CONTEXT *ctx, const char *path, bool is_final, tpm2_session **session) { tool_rc rc = tool_rc_general_error; tpm2_session *s = NULL; /* * Copy the string internally so callers need * not worry about it. */ char *dup_path = strdup(path); if (!dup_path) { LOG_ERR("oom"); return tool_rc_general_error; } FILE *f = fopen(dup_path, "rb"); if (!f) { LOG_ERR("Could not open path \"%s\", due to error: \"%s\"", dup_path, strerror(errno)); free(dup_path); return tool_rc_general_error; } uint32_t version; bool result = files_read_header(f, &version); TPM2_SE type; result = files_read_bytes(f, &type, sizeof(type)); if (!result) { LOG_ERR("Could not read session type"); goto out; } TPMI_ALG_HASH auth_hash; result = files_read_16(f, &auth_hash); if (!result) { LOG_ERR("Could not read session digest algorithm"); goto out; } ESYS_TR handle; tool_rc tmp_rc = files_load_tpm_context_from_file(ctx, &handle, f); if (tmp_rc != tool_rc_success) { rc = tmp_rc; LOG_ERR("Could not load session context"); goto out; } tpm2_session_data *d = tpm2_session_data_new(type); if (!d) { LOG_ERR("oom"); goto out; } tpm2_session_set_authhash(d, auth_hash); tmp_rc = tpm2_session_open(NULL, d, &s); if (tmp_rc != tool_rc_success) { rc = tmp_rc; LOG_ERR("oom new session object"); goto out; } s->output.session_handle = handle; s->internal.path = dup_path; s->internal.ectx = ctx; dup_path = NULL; TPMA_SESSION attrs = 0; if (ctx) { /* hack this in here, should be done when starting the session */ tmp_rc = tpm2_sess_get_attributes(ctx, handle, &attrs); UNUSED(tmp_rc); } s->internal.is_final = is_final; *session = s; LOG_INFO("Restored session: ESYS_TR(0x%x) attrs(0x%x)", handle, attrs); rc = tool_rc_success; out: free(dup_path); if (f) { fclose(f); } return rc; } tool_rc tpm2_session_get_noncetpm(ESYS_CONTEXT *ectx, tpm2_session *s, TPM2B_NONCE **nonce_tpm) { ESYS_TR session_handle = tpm2_session_get_handle(s); return tpm2_sess_get_noncetpm(ectx, session_handle, nonce_tpm); } tool_rc tpm2_session_close(tpm2_session **s) { if (!*s) { return tool_rc_success; } /* * Do not back up: * - password sessions are implicit * - hmac sessions live the life of the tool */ tool_rc rc = tool_rc_success; tpm2_session *session = *s; if (session->output.session_handle == ESYS_TR_PASSWORD) { goto out2; } const char *path = session->internal.path; FILE *session_file = path ? fopen(path, "w+b") : NULL; if (path && !session_file) { LOG_ERR("Could not open path \"%s\", due to error: \"%s\"", path, strerror(errno)); rc = tool_rc_general_error; goto out; } bool flush = path ? session->internal.is_final : true; if (flush) { rc = tpm2_flush_context(session->internal.ectx, session->output.session_handle); /* done, use rc to indicate status */ goto out; } /* * Now write the session_type, handle and auth hash data to disk */ bool result = files_write_header(session_file, SESSION_VERSION); if (!result) { LOG_ERR("Could not write context file header"); rc = tool_rc_general_error; goto out; } // UINT8 session type: TPM2_SE session_type = session->input->session_type; result = files_write_bytes(session_file, &session_type, sizeof(session_type)); if (!result) { LOG_ERR("Could not write session type"); rc = tool_rc_general_error; goto out; } // UINT16 - auth hash digest TPMI_ALG_HASH hash = tpm2_session_get_authhash(session); result = files_write_16(session_file, hash); if (!result) { LOG_ERR("Could not write auth hash"); rc = tool_rc_general_error; goto out; } /* * Save session context at end of tpm2_session. With tabrmd support it * can be reloaded under certain circumstances. */ ESYS_TR handle = tpm2_session_get_handle(session); LOG_INFO("Saved session: ESYS_TR(0x%x)", handle); rc = files_save_tpm_context_to_file(session->internal.ectx, handle, session_file); if (rc != tool_rc_success) { LOG_ERR("Could not write session context"); /* done, free session resources and use rc to indicate status */ } out: if (session_file) { fclose(session_file); } out2: tpm2_session_free(s); return rc; } tool_rc tpm2_session_restart(ESYS_CONTEXT *context, tpm2_session *s) { ESYS_TR handle = tpm2_session_get_handle(s); return tpm2_policy_restart(context, handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE); } tpm2-tools-5.2/lib/tpm2_session.h000066400000000000000000000136351412464516500167640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SRC_TPM2_SESSION_H_ #define SRC_TPM2_SESSION_H_ #include #include #include "tool_rc.h" typedef struct tpm2_session_data tpm2_session_data; typedef struct tpm2_session tpm2_session; /** * Creates a new session data object, based around the inputs to * TPM2_StartAuthSession as listed in Section 11.1: * https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf * * The defaults are set to: * tpmKey = TPM2_RH_NULL * bind = TPM2_RH_NULL * nonceCaller = a SHA1 hash of all 0s. * symmetric = TPM2_ALG_NULL * authHash = TPM2_ALG_SHA256 ^ * * @param type * The type of policy session, one of: * - TPM2_SE_HMAC - For an HMAC session. * - TPM2_SE_POLICY - For a policy session. * - TPM2_SE_TRIAL - For a trial session, useful for building policies. * @return * A tpm2_session_data object on success, NULL on failure. */ tpm2_session_data *tpm2_session_data_new(TPM2_SE type); /** * Sets the tpmKey parameter. * @param data * The session data object to modify. * @param key * The tpmKey parameter value itself. */ void tpm2_session_set_key(tpm2_session_data *data, TPMI_DH_OBJECT key); /** * Sets the nonceCaller parameter. * @param data * The session data object to modify. * @param nonce * The nonce parameter value itself. */ void tpm2_session_set_nonce_caller(tpm2_session_data *data, TPM2B_NONCE *nonce); /** * Retrieves the session nonce * * @param ectx * The ESAPI context * @param session * The session started * @param nonce_tpm * The nonceTPM for the session * */ tool_rc tpm2_session_get_noncetpm(ESYS_CONTEXT *ectx, tpm2_session *session, TPM2B_NONCE **nonce_tpm); /** * Sets the bind parameter. * @param data * The session data object to modify. * @param bind * The bind parameter value itself. */ void tpm2_session_set_bind(tpm2_session_data *data, TPMI_DH_ENTITY bind); /** * Sets the symmetric parameter. * @param data * The session data object to modify. * @param symmetric * The symmetric parameter value itself. */ void tpm2_session_set_symmetric(tpm2_session_data *data, TPMT_SYM_DEF *symmetric); /** * Sets the authHash parameter. * @param data * The session data object to modify. * @param auth_hash * The authHash parameter value itself. */ void tpm2_session_set_authhash(tpm2_session_data *data, TPMI_ALG_HASH auth_hash); void tpm2_session_set_path(tpm2_session_data *data, const char *path); /** * Set the session attributes * @param data * The session data to set * @param attrs * The session attributes to use. */ void tpm2_session_set_attrs(tpm2_session_data *data, TPMA_SESSION attrs); /** * Retrieves the authHash parameter used to start the authorization session. * @param session * The tpm2_session started with tpm2_session_new(). * @return * The authHash value. */ TPMI_ALG_HASH tpm2_session_get_authhash(tpm2_session *session); /** * Retrieves the session handle from starting the authorization session * with tpm2_session_new(). * @param session * The session started with tpm2_session_new(). * @return * The session handle. */ ESYS_TR tpm2_session_get_handle(tpm2_session *session); /** * Retrieves the type of session, ie trial or policy session. * @param session * @return * The type of the session, either TPM2_SE_HMAC, TPM2_SE_POLICY or * TPM2_SE_TRIAL. */ TPM2_SE tpm2_session_get_type(tpm2_session *session); /** * True if a session is of type TPM2_SE_TRIAL * @param session * The session to check the type of. * @return * True if a session is of type TPM2_SE_TRIAL, false otherwise. */ static inline bool tpm2_session_is_trial(tpm2_session *session) { return tpm2_session_get_type(session) == TPM2_SE_TRIAL; } /** * Starts a session with the tpm via StartAuthSession(). * @param context * The Enhanced System API (ESAPI) context. * @param data * A session data object created with tpm2_session_data_new() and potentially * modified with the tpm2_session_data_set_*() routines. * This pointer is owned by the tpm2_session object and the caller can * forget about it at this point. * @param session * The output session on success. * @return * A tool_rc indicating status. */ tool_rc tpm2_session_open(ESYS_CONTEXT *context, tpm2_session_data *data, tpm2_session **session); /** * Saves session data to disk allowing tpm2_session_from_file() to * restore the session if applicable and frees resources. * * @Note * This is accomplished by calling: * - Eys_ContextSave - marks to some RMs like tpm2-abrmd not to flush this session * handle on client disconnection. * - Eys_ContextLoad - restores the session so it can be used. * - Saving a custom file format at path - records the handle and algorithm. * @param session * The session context to save * @return * tool_rc indicating status. */ tool_rc tpm2_session_close(tpm2_session **session); /** * Restores a session saved with tpm2_session_save(). * @param context * The Enhanced System API (ESAPI) context * @param path * The path to restore from. * @param is_final * True if this is is the last tool to use the session, causes a flush. * @param session * The session * @return * tool_rc indicating status. */ tool_rc tpm2_session_restore(ESYS_CONTEXT *ctx, const char *path, bool is_final, tpm2_session **session); /** * restarts the session to it's initial state via a call to * PolicyRestart(). * @param context * The Enhanced System API (ESAPI) context * @param s * The session * @return * tool_rc indicating status. */ tool_rc tpm2_session_restart(ESYS_CONTEXT *context, tpm2_session *s); tpm2_session_data *tpm2_hmac_session_data_new(TPM2B_AUTH *auth_value); void tpm2_session_set_auth_value(tpm2_session *session, TPM2B_AUTH *auth_value); const TPM2B_AUTH *tpm2_session_get_auth_value(tpm2_session *session); #endif /* SRC_TPM2_SESSION_H_ */ tpm2-tools-5.2/lib/tpm2_systemdeps.h000066400000000000000000000003041412464516500174660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef SYSTEM_H #define SYSTEM_H #if defined __FreeBSD__ || defined __DragonFly__ # include #else # include #endif #endif tpm2-tools-5.2/lib/tpm2_tool_output.c000066400000000000000000000000621412464516500176570ustar00rootroot00000000000000#include bool output_enabled = true; tpm2-tools-5.2/lib/tpm2_tool_output.h000066400000000000000000000014411412464516500176660ustar00rootroot00000000000000#ifndef TPM2_TOOL_OUTPUT_H #define TPM2_TOOL_OUTPUT_H #include extern bool output_enabled; /** * Output is enabled by default. This wrapper prevents code that * must disable output from accessing the global 'output_enabled' * variable directly. */ #define tpm2_tool_output_disable() (output_enabled = false) /** * prints output to stdout respecting the quiet option. * Ie when quiet, don't print. * @param fmt * The format specifier, ala printf. * @param ... * The varargs, just like printf. */ #define tpm2_tool_output(fmt, ...) \ do { \ if (output_enabled) { \ printf(fmt, ##__VA_ARGS__); \ } \ } while (0) #endif tpm2-tools-5.2/lib/tpm2_util.c000066400000000000000000001053111412464516500162420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tool_rc.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_session.h" #include "tpm2_tool.h" #include "tpm2_util.h" // verify that the quote digest equals the digest we calculated bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest, TPM2B_DIGEST *pcr_digest) { // Sanity check -- they should at least be same size! if (quoteDigest->size != pcr_digest->size) { LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!"); return false; } // Compare running digest with quote's digest int k; for (k = 0; k < quoteDigest->size; k++) { if (quoteDigest->buffer[k] != pcr_digest->buffer[k]) { LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!"); return false; } } return true; } bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append) { if (!result || !append) { return false; } if (((UINT32)result->size + append->size) > TPM2_MAX_DIGEST_BUFFER) { return false; } memcpy(&result->buffer[result->size], append->buffer, append->size); result->size += append->size; return true; } bool tpm2_util_string_to_uint8(const char *str, uint8_t *value) { uint32_t tmp; bool result = tpm2_util_string_to_uint32(str, &tmp); if (!result) { return false; } /* overflow on 8 bits? */ if (tmp > UINT8_MAX) { return false; } *value = (uint8_t) tmp; return true; } bool tpm2_util_string_to_uint16(const char *str, uint16_t *value) { uint32_t tmp; bool result = tpm2_util_string_to_uint32(str, &tmp); if (!result) { return false; } /* overflow on 16 bits? */ if (tmp > UINT16_MAX) { return false; } *value = (uint16_t) tmp; return true; } bool tpm2_util_string_to_uint32(const char *str, uint32_t *value) { char *endptr; if (str == NULL || *str == '\0') { return false; } /* clear errno before the call, should be 0 afterwards */ errno = 0; unsigned long int tmp = strtoul(str, &endptr, 0); if (errno || tmp > UINT32_MAX) { return false; } /* * The entire string should be able to be converted or fail * We already checked that str starts with a null byte, so no * need to check that again per the man page. */ if (*endptr != '\0') { return false; } *value = (uint32_t) tmp; return true; } bool tpm2_util_string_to_uint64(const char *str, uint64_t *value) { char *endptr; if (str == NULL || *str == '\0') { return false; } /* clear errno before the call, should be 0 afterwards */ errno = 0; /* * unsigned long long is at least 64 bits, although commonly just 64 bits even on 64 bit systems * however, ensure that on some weird system it isn't greater than 64 bits since it is allowed by * the standard. */ unsigned long long int tmp = strtoull(str, &endptr, 0); if (errno || tmp > UINT64_MAX) { return false; } /* * The entire string should be able to be converted or fail * We already checked that str starts with a null byte, so no * need to check that again per the man page. */ if (*endptr != '\0') { return false; } *value = (uint64_t) tmp; return true; } bool tpm2_util_string_to_int32(const char *str, int32_t *value) { char *endptr; if (str == NULL || *str == '\0') { return false; } /* clear errno before the call, should be 0 afterwards */ errno = 0; signed long int tmp = strtol(str, &endptr, 0); if (errno || tmp > INT32_MAX) { return false; } /* * The entire string should be able to be converted or fail * We already checked that str starts with a null byte, so no * need to check that again per the man page. */ if (*endptr != '\0') { return false; } *value = (int32_t) tmp; return true; } int tpm2_util_hex_to_byte_structure(const char *input_string, UINT16 *byte_length, BYTE *byte_buffer) { int str_length; //if the input_string likes "1a2b...", no prefix "0x" int i = 0; if (input_string == NULL || byte_length == NULL || byte_buffer == NULL) return -1; str_length = strlen(input_string); if (str_length % 2) return -2; for (i = 0; i < str_length; i++) { if (!isxdigit(input_string[i])) return -3; } if (*byte_length < str_length / 2) return -4; *byte_length = str_length / 2; for (i = 0; i < *byte_length; i++) { char tmp_str[4] = { 0 }; tmp_str[0] = input_string[i * 2]; tmp_str[1] = input_string[i * 2 + 1]; byte_buffer[i] = strtol(tmp_str, NULL, 16); } return 0; } bool tpm2_util_bin_from_hex_or_file(const char *input, UINT16 *len, BYTE *buffer) { bool result = false; FILE *f = fopen(input, "rb"); if (!f) { result = tpm2_util_hex_to_byte_structure(input, len, buffer) == 0; goto out; } result = file_read_bytes_from_file(f, buffer, len, input); fclose(f); out: if (!result) { LOG_ERR("Could not convert \"%s\". Neither a file path nor hex string.", input); } return result; } void tpm2_util_hexdump2(FILE *f, const BYTE *data, size_t len) { size_t i; for (i = 0; i < len; i++) { fprintf(f, "%02x", data[i]); } } void tpm2_util_hexdump(const BYTE *data, size_t len) { if (!output_enabled) { return; } tpm2_util_hexdump2(stdout, data, len); } bool tpm2_util_is_big_endian(void) { uint32_t test_word; uint8_t *test_byte; test_word = 0xFF000000; test_byte = (uint8_t *) (&test_word); return test_byte[0] == 0xFF; } #define STRING_BYTES_ENDIAN_CONVERT(size) \ UINT##size tpm2_util_endian_swap_##size(UINT##size data) { \ \ UINT##size converted; \ UINT8 *bytes = (UINT8 *)&data; \ UINT8 *tmp = (UINT8 *)&converted; \ \ size_t i; \ for(i=0; i < sizeof(UINT##size); i ++) { \ tmp[i] = bytes[sizeof(UINT##size) - i - 1]; \ } \ \ return converted; \ } STRING_BYTES_ENDIAN_CONVERT(16) STRING_BYTES_ENDIAN_CONVERT(32) STRING_BYTES_ENDIAN_CONVERT(64) #define STRING_BYTES_ENDIAN_HTON(size) \ UINT##size tpm2_util_hton_##size(UINT##size data) { \ \ bool is_big_endian = tpm2_util_is_big_endian(); \ if (is_big_endian) { \ return data; \ } \ \ return tpm2_util_endian_swap_##size(data); \ } STRING_BYTES_ENDIAN_HTON(16) STRING_BYTES_ENDIAN_HTON(32) STRING_BYTES_ENDIAN_HTON(64) /* * Converting from host-to-network (hton) or network-to-host (ntoh) is * the same operation: if endianess differs between host and data, swap * endianess. Thus we can just call the hton routines, but have some nice * names for folks. */ UINT16 tpm2_util_ntoh_16(UINT16 data) { return tpm2_util_hton_16(data); } UINT32 tpm2_util_ntoh_32(UINT32 data) { return tpm2_util_hton_32(data); } UINT64 tpm2_util_ntoh_64(UINT64 data) { return tpm2_util_hton_64(data); } UINT32 tpm2_util_pop_count(UINT32 data) { static const UINT8 bits_per_nibble[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; UINT8 count = 0; UINT8 *d = (UINT8 *) &data; size_t i; for (i = 0; i < sizeof(data); i++) { count += bits_per_nibble[d[i] & 0x0f]; count += bits_per_nibble[d[i] >> 4]; } return count; } #define TPM2_UTIL_KEYDATA_INIT { .len = 0 }; typedef struct tpm2_util_keydata tpm2_util_keydata; struct tpm2_util_keydata { UINT16 len; struct { const char *name; TPM2B *value; } entries[2]; }; static void tpm2_util_public_to_keydata(TPMT_PUBLIC *public, tpm2_util_keydata *keydata) { switch (public->type) { case TPM2_ALG_RSA: keydata->len = 1; keydata->entries[0].name = tpm2_alg_util_algtostr( public->type, tpm2_alg_util_flags_any); keydata->entries[0].value = (TPM2B *) &public->unique.rsa; return; case TPM2_ALG_KEYEDHASH: keydata->len = 1; keydata->entries[0].name = tpm2_alg_util_algtostr( public->type, tpm2_alg_util_flags_any); keydata->entries[0].value = (TPM2B *) &public->unique.keyedHash; return; case TPM2_ALG_SYMCIPHER: keydata->len = 1; keydata->entries[0].name = tpm2_alg_util_algtostr( public->type, tpm2_alg_util_flags_any); keydata->entries[0].value = (TPM2B *) &public->unique.sym; return; case TPM2_ALG_ECC: keydata->len = 2; keydata->entries[0].name = "x"; keydata->entries[0].value = (TPM2B *) &public->unique.ecc.x; keydata->entries[1].name = "y"; keydata->entries[1].value = (TPM2B *) &public->unique.ecc.y; return; default: LOG_WARN("The algorithm type(0x%4.4x) is not supported", public->type); } return; } void print_yaml_indent(size_t indent_count) { while (indent_count--) { tpm2_tool_output(" "); } } void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj, char *indent) { if (!indent) { indent = ""; } char *attrs = tpm2_attr_util_obj_attrtostr(obj); tpm2_tool_output("%sattributes:\n", indent); tpm2_tool_output("%s value: %s\n", indent, attrs); tpm2_tool_output("%s raw: 0x%x\n", indent, obj); free(attrs); } static void print_alg_raw(const char *name, TPM2_ALG_ID alg, const char *indent) { tpm2_tool_output("%s%s:\n", indent, name); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(alg, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, alg); } static void print_scheme_common(TPMI_ALG_RSA_SCHEME scheme, const char *indent) { print_alg_raw("scheme", scheme, indent); } static void print_sym(TPMT_SYM_DEF_OBJECT *sym, const char *indent) { print_alg_raw("sym-alg", sym->algorithm, indent); print_alg_raw("sym-mode", sym->mode.sym, indent); tpm2_tool_output("%ssym-keybits: %u\n", indent, sym->keyBits.sym); } static void print_rsa_scheme(TPMT_RSA_SCHEME *scheme, const char *indent) { print_scheme_common(scheme->scheme, indent); /* * everything is a union on a hash algorithm except for RSAES which * has nothing. So on RSAES skip the hash algorithm printing */ if (scheme->scheme != TPM2_ALG_RSAES) { print_alg_raw("scheme-halg", scheme->details.oaep.hashAlg, indent); } } static void print_ecc_scheme(TPMT_ECC_SCHEME *scheme, const char *indent) { print_scheme_common(scheme->scheme, indent); /* * everything but ecdaa uses only hash alg * in a union, so we only need to do things differently * for ecdaa. */ print_alg_raw("scheme-halg", scheme->details.oaep.hashAlg, indent); if (scheme->scheme == TPM2_ALG_ECDAA) { tpm2_tool_output("%sscheme-count: %u\n", indent, scheme->details.ecdaa.count); } } static void print_kdf_scheme(TPMT_KDF_SCHEME *kdf, const char *indent) { print_alg_raw("kdfa-alg", kdf->scheme, indent); /* * The hash algorithm for the KDFA is in a union, just grab one of them. */ print_alg_raw("kdfa-halg", kdf->details.mgf1.hashAlg, indent); } void tpm2_util_tpmt_public_to_yaml(TPMT_PUBLIC *public, char *indent) { if (!indent) { indent = ""; } tpm2_tool_output("%sname-alg:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(public->nameAlg, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, public->nameAlg); tpm2_util_tpma_object_to_yaml(public->objectAttributes, indent); tpm2_tool_output("%stype:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(public->type, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, public->type); switch (public->type) { case TPM2_ALG_SYMCIPHER: { TPMS_SYMCIPHER_PARMS *s = &public->parameters.symDetail; print_sym(&s->sym, indent); } break; case TPM2_ALG_KEYEDHASH: { TPMS_KEYEDHASH_PARMS *k = &public->parameters.keyedHashDetail; tpm2_tool_output("%salgorithm: \n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(k->scheme.scheme, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, k->scheme.scheme); if (k->scheme.scheme == TPM2_ALG_HMAC) { tpm2_tool_output("%shash-alg:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(k->scheme.details.hmac.hashAlg, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, k->scheme.details.hmac.hashAlg); } else if (k->scheme.scheme == TPM2_ALG_XOR) { tpm2_tool_output("%shash-alg:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr( k->scheme.details.exclusiveOr.hashAlg, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, k->scheme.details.exclusiveOr.hashAlg); tpm2_tool_output("%skdfa-alg:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_algtostr(k->scheme.details.exclusiveOr.kdf, tpm2_alg_util_flags_any)); tpm2_tool_output("%s raw: 0x%x\n", indent, k->scheme.details.exclusiveOr.kdf); } } break; case TPM2_ALG_RSA: { TPMS_RSA_PARMS *r = &public->parameters.rsaDetail; tpm2_tool_output("%sexponent: %u\n", indent, r->exponent ? r->exponent : 65537); tpm2_tool_output("%sbits: %u\n", indent, r->keyBits); print_rsa_scheme(&r->scheme, indent); print_sym(&r->symmetric, indent); } break; case TPM2_ALG_ECC: { TPMS_ECC_PARMS *e = &public->parameters.eccDetail; tpm2_tool_output("%scurve-id:\n", indent); tpm2_tool_output("%s value: %s\n", indent, tpm2_alg_util_ecc_to_str(e->curveID)); tpm2_tool_output("%s raw: 0x%x\n", indent, e->curveID); print_kdf_scheme(&e->kdf, indent); print_ecc_scheme(&e->scheme, indent); print_sym(&e->symmetric, indent); } break; } tpm2_util_keydata keydata = TPM2_UTIL_KEYDATA_INIT ; tpm2_util_public_to_keydata(public, &keydata); UINT16 i; /* if no keydata len will be 0 and it wont print */ for (i = 0; i < keydata.len; i++) { tpm2_tool_output("%s%s: ", indent, keydata.entries[i].name); tpm2_util_print_tpm2b(keydata.entries[i].value); tpm2_tool_output("%s\n", indent); } if (public->authPolicy.size) { tpm2_tool_output("%sauthorization policy: ", indent); tpm2_util_hexdump(public->authPolicy.buffer, public->authPolicy.size); tpm2_tool_output("%s\n", indent); } } void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public, char *indent) { tpm2_util_tpmt_public_to_yaml(&public->publicArea, indent); } bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg, TPM2B_PRIVATE_VENDOR_SPECIFIC *key, TPM2B_DIGEST *seed, TPM2B_DIGEST *unique_data) { TPM2B_MAX_BUFFER buf = { .size = key->size + seed->size }; if (buf.size > sizeof(buf.buffer)) { LOG_ERR("Seed and key size are too big"); return false; } memcpy(buf.buffer, seed->buffer, seed->size); memcpy(&buf.buffer[seed->size], key->buffer, key->size); const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(name_alg); if (!md) { LOG_ERR("Algorithm not supported: %x", name_alg); return false; } unsigned int hash_size; int rc = EVP_Digest(buf.buffer, buf.size, unique_data->buffer, &hash_size, md, NULL); if (!rc) { LOG_ERR("Hash calculation failed"); return false; } unique_data->size = hash_size; return true; } ESYS_TR tpm2_tpmi_hierarchy_to_esys_tr(TPMI_RH_PROVISION inh) { switch (inh) { case TPM2_RH_OWNER: return ESYS_TR_RH_OWNER; case TPM2_RH_PLATFORM: return ESYS_TR_RH_PLATFORM; case TPM2_RH_ENDORSEMENT: return ESYS_TR_RH_ENDORSEMENT; case TPM2_RH_NULL: return ESYS_TR_RH_NULL; case TPM2_RH_LOCKOUT: return ESYS_TR_RH_LOCKOUT; } return ESYS_TR_NONE; } tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context, TPM2_HANDLE sys_handle, ESYS_TR *esys_handle) { ESYS_TR h = tpm2_tpmi_hierarchy_to_esys_tr(sys_handle); if (h != ESYS_TR_NONE) { *esys_handle = h; return tool_rc_success; } return tpm2_from_tpm_public(context, sys_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, esys_handle); } char *tpm2_util_getenv(const char *name) { return getenv(name); } /** * Parses a hierarchy value from an option argument. * @param value * The string to parse, which can be a numerical string as * understood by strtoul() with a base of 0, or an: * - o - Owner hierarchy * - p - Platform hierarchy * - e - Endorsement hierarchy * - n - Null hierarchy * @param hierarchy * The parsed hierarchy as output. * @param flags * What hierarchies should be supported by * the parsing. * @return * True on success, False otherwise. */ static bool filter_hierarchy_handles(TPMI_RH_PROVISION hierarchy, tpm2_handle_flags flags) { switch (hierarchy) { case TPM2_RH_OWNER: if (!(flags & TPM2_HANDLE_FLAGS_O)) { LOG_ERR("Unexpected handle - TPM2_RH_OWNER"); return false; } break; case TPM2_RH_PLATFORM: if (!(flags & TPM2_HANDLE_FLAGS_P)) { LOG_ERR("Unexpected handle - TPM2_RH_PLATFORM"); return false; } break; case TPM2_RH_ENDORSEMENT: if (!(flags & TPM2_HANDLE_FLAGS_E)) { LOG_ERR("Unexpected handle - TPM2_RH_ENDORSEMENT"); return false; } break; case TPM2_RH_NULL: if (!(flags & TPM2_HANDLE_FLAGS_N)) { LOG_ERR("Unexpected handle - TPM2_RH_NULL"); return false; } break; case TPM2_RH_LOCKOUT: if (!(flags & TPM2_HANDLE_FLAGS_L)) { LOG_ERR("Unexpected handle - TPM2_RH_LOCKOUT"); return false; } break; default: //If specified a random offset to the permanent handle range if (flags == TPM2_HANDLE_ALL_W_NV || flags == TPM2_HANDLE_FLAGS_NONE) { return true; } return false; } return true; } static bool filter_handles(TPMI_RH_PROVISION *hierarchy, tpm2_handle_flags flags) { TPM2_RH range = *hierarchy & TPM2_HR_RANGE_MASK; /* * if their is no range, then it could be NV or PCR, use flags * to figure out what it is. */ if (range == 0) { if (flags & TPM2_HANDLE_FLAGS_NV) { *hierarchy += TPM2_HR_NV_INDEX; range = *hierarchy & TPM2_HR_RANGE_MASK; } else if (flags & TPM2_HANDLE_FLAGS_PCR) { *hierarchy += TPM2_HR_PCR; range = *hierarchy & TPM2_HR_RANGE_MASK; } else { LOG_ERR("Implicit indices are not supported."); return false; } } /* now that we have fixed up any non-ranged handles, check them */ if (range == TPM2_HR_NV_INDEX) { if (!(flags & TPM2_HANDLE_FLAGS_NV)) { LOG_ERR("NV-Index handles are not supported by this command."); return false; } if (*hierarchy < TPM2_NV_INDEX_FIRST || *hierarchy > TPM2_NV_INDEX_LAST) { LOG_ERR("NV-Index handle is out of range."); return false; } return true; } else if (range == TPM2_HR_PCR) { if (!(flags & TPM2_HANDLE_FLAGS_PCR)) { LOG_ERR("PCR handles are not supported by this command."); return false; } /* first is 0 so no possible way unsigned is less than 0, thus no check */ if (*hierarchy > TPM2_PCR_LAST) { LOG_ERR("PCR handle out of range."); return false; } return true; } else if (range == TPM2_HR_TRANSIENT) { if (!(flags & TPM2_HANDLES_FLAGS_TRANSIENT)) { LOG_ERR("Transient handles are not supported by this command."); return false; } return true; } else if (range == TPM2_HR_PERMANENT) { return filter_hierarchy_handles(*hierarchy, flags); } else if (range == TPM2_HR_PERSISTENT) { if (!(flags & TPM2_HANDLES_FLAGS_PERSISTENT)) { LOG_ERR("Persistent handles are not supported by this command."); return false; } if (*hierarchy < TPM2_PERSISTENT_FIRST || *hierarchy > TPM2_PERSISTENT_LAST) { LOG_ERR("Persistent handle out of range."); return false; } return true; } /* else its a session flag and shouldn't use this interface */ return false; } bool tpm2_util_handle_from_optarg(const char *value, TPMI_RH_PROVISION *hierarchy, tpm2_handle_flags flags) { if (!value || !value[0]) { return false; } if ((flags & TPM2_HANDLE_FLAGS_NV) && (flags & TPM2_HANDLE_FLAGS_PCR)) { LOG_ERR("Cannot specify NV and PCR index together"); return false; } *hierarchy = 0; bool is_o = !strncmp(value, "owner", strlen(value)); if (is_o) { *hierarchy = TPM2_RH_OWNER; } bool is_p = !strncmp(value, "platform", strlen(value)); if (is_p) { *hierarchy = TPM2_RH_PLATFORM; } bool is_e = !strncmp(value, "endorsement", strlen(value)); if (is_e) { *hierarchy = TPM2_RH_ENDORSEMENT; } bool is_n = !strncmp(value, "null", strlen(value)); if (is_n) { *hierarchy = TPM2_RH_NULL; } bool is_l = !strncmp(value, "lockout", strlen(value)); if (is_l) { *hierarchy = TPM2_RH_LOCKOUT; } bool result = true; if (!*hierarchy) { /* * This branch is executed when hierarchy is specified as a hex handle. * The raw hex returned may be a generic (non hierarchy) TPM2_HANDLE. */ result = tpm2_util_string_to_uint32(value, hierarchy); } if (!result) { char msg[256] = { 0 }; char print_flags[32] = { '[', '\0' }; if (flags & TPM2_HANDLE_FLAGS_O) { strncat(print_flags, "o|", sizeof(print_flags) - strlen(print_flags) - 1); } if (flags & TPM2_HANDLE_FLAGS_P) { strncat(print_flags, "p|", sizeof(print_flags) - strlen(print_flags) - 1); } if (flags & TPM2_HANDLE_FLAGS_E) { strncat(print_flags, "e|", sizeof(print_flags) - strlen(print_flags) - 1); } if (flags & TPM2_HANDLE_FLAGS_N) { strncat(print_flags, "n|", sizeof(print_flags) - strlen(print_flags) - 1); } if (flags & TPM2_HANDLE_FLAGS_L) { strncat(print_flags, "l|", sizeof(print_flags) - strlen(print_flags) - 1); } size_t len = strlen(print_flags); if (print_flags[len - 1] == '|') { len--; print_flags[len] = '\0'; } strncat(print_flags, "]", sizeof(print_flags) - strlen(print_flags) - 1); len++; bool has_print_flags = len > 2; if (has_print_flags) { snprintf(msg, sizeof(msg), "expected %s or ", print_flags); } strncat(msg, "a handle number", sizeof(msg) - strlen(msg) - 1); LOG_ERR("Incorrect handle value, got: \"%s\", expected %s", value, msg); return false; } /* * If the caller specifies the expected valid hierarchies, either as string, * or hex handles, they are additionally filtered here. */ bool res = filter_handles(hierarchy, flags); if (!res) { LOG_ERR("Unknown or unsupported handle, got: \"%s\"", value); } return res; } bool tpm2_util_get_label(const char *value, TPM2B_DATA *label) { if (!value) { label->size = 0; return true; } FILE *f = fopen(value, "rb"); if (f) { /* set size one smaller for NUL byte */ label->size = sizeof(label->buffer) - 1; size_t cnt = fread(label->buffer, 1, label->size, f); if (!feof(f)) { LOG_ERR("label file \"%s\" larger than expected. Expected %u", value, label->size); fclose(f); return false; } if (ferror(f)) { LOG_ERR("reading label file \"%s\" error: %s", value, strerror(errno)); fclose(f); return false; } fclose(f); label->size = cnt; /* Set NUL byte and increment */ label->buffer[label->size++] = '\0'; return true; } size_t len = strlen(value); if (len > sizeof(label->buffer) - 1) { LOG_ERR("label file \"%s\" larger than expected. Expected %zu", value, sizeof(label->buffer) - 1); return false; } memcpy(label->buffer, value, len); label->size = len; /* Set NUL byte and increment */ label->buffer[label->size++] = '\0'; return true; } void tpm2_util_print_time(const TPMS_TIME_INFO *current_time) { tpm2_tool_output("time: %"PRIu64"\n", current_time->time); tpm2_tool_output("clock_info:\n"); tpm2_tool_output(" clock: %"PRIu64"\n", current_time->clockInfo.clock); tpm2_tool_output(" reset_count: %"PRIu32"\n", current_time->clockInfo.resetCount); tpm2_tool_output(" restart_count: %"PRIu32"\n", current_time->clockInfo.restartCount); tpm2_tool_output(" safe: %s\n", current_time->clockInfo.safe ? "yes" : "no"); } bool tpm2_calq_qname(TPM2B_NAME *pqname, TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname) { // QNB ≔ HB (QNA || NAMEB) bool result = false; const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(halg); EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if (!mdctx) { LOG_ERR("%s", tpm2_openssl_get_err()); return false; } int rc = EVP_DigestInit_ex(mdctx, md, NULL); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } size_t offset = sizeof(halg); rc = EVP_DigestUpdate(mdctx, pqname->name, pqname->size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } rc = EVP_DigestUpdate(mdctx, name->name, name->size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } unsigned size = EVP_MD_size(md); rc = EVP_DigestFinal_ex(mdctx, &qname->name[offset], &size); if (!rc) { LOG_ERR("%s", tpm2_openssl_get_err()); goto out; } /* hash sizes are not bigger than 16 bits, safe truncate */ qname->size = (UINT16)size; /* put the hash alg on the front, since name already has it in marshalled * proper form just use it. */ memcpy(qname->name, name->name, offset); qname->size += offset; result = true; out: EVP_MD_CTX_destroy(mdctx); return result; } bool tpm2_safe_read_from_stdin(int length, char *data) { int rc; char *buf = malloc(length); char *read_data = malloc(length); if (buf == fgets(buf, length, stdin)) { rc = sscanf(buf, "%s", read_data); if (rc != 1) { free(buf); free(read_data); return false; } } else { free(buf); free(read_data); return false; } strcpy(data, read_data); free(buf); free(read_data); return true; } bool tpm2_pem_encoded_key_to_fingerprint(const char *pem_encoded_key, char *fingerprint) { bool is_pemkey_len_valid = strlen(pem_encoded_key) > 1024 ? false : true; if (!is_pemkey_len_valid) { return false; } char str[1024] = ""; strcpy(str, pem_encoded_key); /* walk through other tokens */ char base64[1024] = ""; char *token = strtok(str, "\n"); while ( token != NULL ) { if (!strstr(token, "-----")) { bool is_base64_overrun = (strlen(base64) + strlen(token)) > 1024 ? true : false; if (is_base64_overrun) { return false; } strcat(base64, token); } token = strtok(NULL, "\n"); } BYTE buffer[1024]; size_t buffer_length = 0; int rc = tpm2_base64_decode(base64, buffer, &buffer_length); if(!rc){ LOG_ERR("%s", "tpm2_base64_decode"); return false; } TPM2B_DIGEST digest; rc = tpm2_openssl_hash_compute_data(TPM2_ALG_SHA256, buffer, buffer_length, &digest); if(!rc){ LOG_ERR("%s", "tpm2_openssl_hash_compute_data"); return false; } rc = tpm2_base64_encode(buffer, buffer_length, base64); if(!rc){ LOG_ERR("%s", "tpm2_base64_decode"); return false; } strcpy(fingerprint, "SHA256:"); strcat(fingerprint, base64); fingerprint[strlen(fingerprint)-1] = 0; // remove trailing \n return true; } #define MAX_SESSION_CNT 3 tool_rc tpm2_util_aux_sessions_setup(ESYS_CONTEXT *ectx, uint8_t session_cnt, const char **session_path, ESYS_TR *session_handle, tpm2_session **session) { /* * If no aux sessions were specified, simply return. */ if (!session_cnt) { return tool_rc_success; } if (session_cnt > MAX_SESSION_CNT) { LOG_ERR("A max of 3 sessions allowed"); return tool_rc_general_error; } uint8_t session_idx = 0; for (session_idx = 0; session_idx < (session_cnt); session_idx++) { if (session_path[session_idx]) { tool_rc rc = tpm2_session_restore(ectx, session_path[session_idx], false, &session[session_idx]); if (rc != tool_rc_success) { LOG_ERR("Could not restore aux-session #%s", session_path[session_idx]); return rc; } session_handle[session_idx] = tpm2_session_get_handle(session[session_idx]); } } return tool_rc_success; } static TPMI_ALG_HASH calc_phash_alg_from_phash_path(const char **phash_path) { if (!*phash_path) { return TPM2_ALG_ERROR; } /* * Expecting single token, so tokenize just once. */ char *str = malloc(strlen(*phash_path) + 1); strcpy(str, *phash_path); char *token = strtok(str, ":"); TPMI_ALG_HASH hashalg = tpm2_alg_util_from_optarg( token, tpm2_alg_util_flags_hash); /* * Adjust the pHash path to skip the : */ if (hashalg != TPM2_ALG_ERROR) { *phash_path += strlen(token) + 1; } free(str); return hashalg; } static TPMI_ALG_HASH tpm2_util_calc_phash_algorithm_from_session_types( ESYS_CONTEXT *ectx, tpm2_session **sessions) { TPMI_ALG_HASH rethash = TPM2_ALG_ERROR; size_t session_idx = 0; for (session_idx = 0; session_idx < MAX_SESSION_CNT; session_idx++) { if(!sessions[session_idx]) { continue; } /* * Ignore password sessions */ ESYS_TR session_handle = tpm2_session_get_handle(sessions[session_idx]); if(session_handle == ESYS_TR_PASSWORD) { continue; } /* * Ignore trial sessions */ TPM2_SE session_type = tpm2_session_get_type(sessions[session_idx]); if (session_type != TPM2_SE_HMAC && session_type != TPM2_SE_POLICY) { continue; } /* * If this is an audit session, use that session halg. * Note: Audit sessions are always HMAC type. */ if (session_type == TPM2_SE_HMAC) { TPMA_SESSION attrs = 0; tool_rc tmp_rc = tpm2_sess_get_attributes(ectx, session_handle, &attrs); UNUSED(tmp_rc); if (attrs & TPMA_SESSION_AUDIT) { rethash = tpm2_session_get_authhash(sessions[session_idx]); break; } } /* * If no other sessions remain, simply use (policy)sessions halg. */ rethash = tpm2_session_get_authhash(sessions[session_idx]); } return rethash; } /* * It should be noted that the auths aren't checked when calculating the pHash, * instead the sessions are consumed to determine the pHash algorithm. * * 1. If phash_path is preceded with : use that as phash-halg return * Otherwise * * Consume session only if it is a policy-session or an hmac-session * 1. If only hmac or policy session is specified, return that session's halg * 2. If hmac-session with audit is specified, return that session's halg * 3. If policy-session, then return policy-session's halg * * Otherwise * return SHA256 * */ TPMI_ALG_HASH tpm2_util_calculate_phash_algorithm(ESYS_CONTEXT *ectx, const char **cphash_path, TPM2B_DIGEST *cp_hash, const char **rphash_path, TPM2B_DIGEST *rp_hash, tpm2_session **sessions) { /* specified in pHash path */ TPMI_ALG_HASH cphash_alg = cphash_path ? calc_phash_alg_from_phash_path( cphash_path) : TPM2_ALG_ERROR; TPMI_ALG_HASH rphash_alg = rphash_path ? calc_phash_alg_from_phash_path( rphash_path) : TPM2_ALG_ERROR; /* * Default to cphash_alg if both are specified. * This removes the conflict if cphash_alg and rphash_alg don't match. * This also sets the cphash_alg if only rphash_alg is specified and vice * versa. */ TPMI_ALG_HASH phash_alg = cphash_alg != TPM2_ALG_ERROR ? cphash_alg : (rphash_alg != TPM2_ALG_ERROR ? rphash_alg : TPM2_ALG_ERROR); if (phash_alg != TPM2_ALG_ERROR) { goto out; } /* determined from the sessions */ if (sessions) { phash_alg = tpm2_util_calc_phash_algorithm_from_session_types(ectx, sessions); } out: /* defaults to TPM2_ALG_SHA256 if cannot find from path or sessions */ if (phash_alg == TPM2_ALG_ERROR) { phash_alg = TPM2_ALG_SHA256; } /* * Side-effect: Set the size of the cp_hash and/or rp_hash */ if (cphash_path && cp_hash) { cp_hash->size = tpm2_alg_util_get_hash_size(phash_alg); } if (rphash_path && rp_hash) { rp_hash->size = tpm2_alg_util_get_hash_size(phash_alg); } return phash_alg; } tpm2-tools-5.2/lib/tpm2_util.h000066400000000000000000000341641412464516500162560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef STRING_BYTES_H #define STRING_BYTES_H #include #include #include #include #include "tpm2_session.h" #if defined (__GNUC__) #define COMPILER_ATTR(...) __attribute__((__VA_ARGS__)) #else #define COMPILER_ATTR(...) #endif #define xstr(s) str(s) #define str(s) #s #define UNUSED(x) (void)x #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0])) #define PSTR(x) x ? x : "(null)" #define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->field))) #define TSS2_APP_RC_LAYER TSS2_RC_LAYER(5) #define TPM2B_TYPE_INIT(type, field) { .size = BUFFER_SIZE(type, field), } #define TPM2B_INIT(xsize) { .size = xsize, } #define TPM2B_EMPTY_INIT TPM2B_INIT(0) #define TPM2B_SENSITIVE_CREATE_EMPTY_INIT { \ .sensitive = { \ .data = { \ .size = 0 \ }, \ .userAuth = { \ .size = 0 \ } \ } \ } #define TPMT_TK_CREATION_EMPTY_INIT { \ .tag = 0, \ .hierarchy = 0, \ .digest = TPM2B_EMPTY_INIT \ } #define TPML_PCR_SELECTION_EMPTY_INIT { \ .count = 0, \ } //ignore pcrSelections since count is 0. #define TPMS_CAPABILITY_DATA_EMPTY_INIT { \ .capability = 0, \ } // ignore data since capability is 0. #define TPMT_TK_HASHCHECK_EMPTY_INIT { \ .tag = 0, \ .hierarchy = 0, \ .digest = TPM2B_EMPTY_INIT \ } #define TSS2L_SYS_AUTH_COMMAND_INIT(cnt, array) { \ .count = cnt, \ .auths = array, \ } /* * This macro is useful as a wrapper around SAPI functions to automatically * retry function calls when the RC is TPM2_RC_RETRY. */ #define TSS2_RETRY_EXP(expression) \ ({ \ TSS2_RC __result = 0; \ do { \ __result = (expression); \ } while (tpm2_error_get(__result) == TPM2_RC_RETRY); \ __result; \ }) typedef struct { UINT16 size; BYTE buffer[0]; } TPM2B; #define DEFAULT_CREATE_ATTRS \ TPMA_OBJECT_DECRYPT|TPMA_OBJECT_SIGN_ENCRYPT|TPMA_OBJECT_FIXEDTPM \ |TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN \ |TPMA_OBJECT_USERWITHAUTH int tpm2_util_hex_to_byte_structure(const char *in_str, UINT16 *byte_length, BYTE *byte_buffer); /** * Compares two digests to ensure they are equal (for validation). * @param quote_digest * The digest from the quote. * @param pcr_digest * The digest calculated off-TMP from the PCRs. * @return * True on success, false otherwise. */ bool tpm2_util_verify_digests(TPM2B_DIGEST *quote_digest, TPM2B_DIGEST *pcr_digest); /** * Appends a TPM2B buffer to a MAX buffer. * @param result * The MAX buffer to append to * @param append * The buffer to append to result. * @return * true on success, false otherwise. */ bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append); /** * Converts a numerical string into a int32_t value. * @param str * The numerical string to convert. * @param value * The value to store the conversion into. * @return * true on success, false otherwise. */ bool tpm2_util_string_to_int32(const char *str, int32_t *value); /** * Converts a numerical string into a uint32 value. * @param str * The numerical string to convert. * @param value * The value to store the conversion into. * @return * true on success, false otherwise. */ bool tpm2_util_string_to_uint32(const char *str, uint32_t *value); /** * Converts a numerical string into a uint64 value. * @param str * The numerical string to convert. * @param value * The value to store the conversion into. * @return * true on success, false otherwise. */ bool tpm2_util_string_to_uint64(const char *str, uint64_t *value); /** * Converts a numerical string into a uint16 value. * @param str * The numerical string to convert. * @param value * The value to store the conversion into. * @return * true on success, false otherwise. */ bool tpm2_util_string_to_uint16(const char *str, uint16_t *value); /** * Converts a numerical string into a uint8 value. * @param str * The numerical string to convert. * @param value * The value to store the conversion into. * @return * true on success, false otherwise. */ bool tpm2_util_string_to_uint8(const char *str, uint8_t *value); /** * Prints an xxd compatible hexdump to stdout if output is enabled, * ie no -Q option. * * @param data * The data to print. * @param len * The length of the data. */ void tpm2_util_hexdump(const BYTE *data, size_t len); /** * Similar to tpm2_util_hexdump(), but: * - does NOT respect the -Q option * - allows specification of the output stream. * @param f * The FILE output stream. * @param data * The data to convert to hex. * @param len * The length of the data. */ void tpm2_util_hexdump2(FILE *f, const BYTE *data, size_t len); /** * Read a hex string converting it to binary or a binary file and * store into a binary buffer. * @param input * Either a hex string or a file path. * @param len * The maximum length of the buffer. * @param buffer * The buffer to read into. * @return * True on success, False otherwise. */ bool tpm2_util_bin_from_hex_or_file(const char *input, UINT16 *len, BYTE *buffer); /** * Prints a TPM2B as a hex dump respecting the -Q option * to stdout. * * @param buffer the TPM2B to print. */ #define tpm2_util_print_tpm2b(b) _tpm2_util_print_tpm2b((TPM2B *)b) static inline void _tpm2_util_print_tpm2b(TPM2B *buffer) { return tpm2_util_hexdump(buffer->buffer, buffer->size); } /** * Prints a TPM2B as a hex dump to the FILE specified. Does NOT * respect -Q like tpm2_util_print_tpm2b(). * * @param out * The output FILE. * @param * buffer the TPM2B to print. */ #define tpm2_util_print_tpm2b2(o, b) _tpm2_util_print_tpm2b2(o, (TPM2B *)b) static inline void _tpm2_util_print_tpm2b2(FILE *out, const TPM2B *buffer) { return tpm2_util_hexdump2(out, buffer->buffer, buffer->size); } /** * Determines if given PCR value is selected in TPMS_PCR_SELECTION structure. * @param pcr_selection the TPMS_PCR_SELECTION structure to check pcr against. * @param pcr the PCR ID to check selection status of. */ static inline bool tpm2_util_is_pcr_select_bit_set( const TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) { return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8))); } /** * Checks if the host is big endian * @return * True of the host is big endian false otherwise. */ bool tpm2_util_is_big_endian(void); /** * Swaps the endianess of 16 bit value. * @param data * A 16 bit value to swap the endianess on. * @return * The 16 bit value with the endianess swapped. */ UINT16 tpm2_util_endian_swap_16(UINT16 data); /** * Just like string_bytes_endian_convert_16 but for 32 bit values. */ UINT32 tpm2_util_endian_swap_32(UINT32 data); /** * Just like string_bytes_endian_convert_16 but for 64 bit values. */ UINT64 tpm2_util_endian_swap_64(UINT64 data); /** * Converts a 16 bit value from host endianess to network endianess. * @param data * The data to possibly swap endianess. * @return * The swapped data. */ UINT16 tpm2_util_hton_16(UINT16 data); /** * Just like string_bytes_endian_hton_16 but for 32 bit values. */ UINT32 tpm2_util_hton_32(UINT32 data); /** * Just like string_bytes_endian_hton_16 but for 64 bit values. */ UINT64 tpm2_util_hton_64(UINT64 data); /** * Converts a 16 bit value from network endianess to host endianess. * @param data * The data to possibly swap endianess. * @return * The swapped data. */ UINT16 tpm2_util_ntoh_16(UINT16 data); /** * Just like string_bytes_endian_ntoh_16 but for 32 bit values. */ UINT32 tpm2_util_ntoh_32(UINT32 data); /** * Just like string_bytes_endian_ntoh_16 but for 64 bit values. */ UINT64 tpm2_util_ntoh_64(UINT64 data); /** * Counts the number of set bits aka a population count. * @param data * The data to count set bits in. * @return * The number of set bits or population count. */ UINT32 tpm2_util_pop_count(UINT32 data); /** * Prints whitespace indention for yaml output. * @param indent_count * Number of times to indent */ void print_yaml_indent(size_t indent_count); /** * Convert a TPM2B_PUBLIC into a yaml format and output if not quiet. * @param public * The TPM2B_PUBLIC to output in YAML format. * @param indent * The level of indentation, can be NULL */ void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public, char *indent); void tpm2_util_tpmt_public_to_yaml(TPMT_PUBLIC *public, char *indent); /** * Convert a TPMA_OBJECT to a yaml format and output if not quiet. * @param obj * The TPMA_OBJECT attributes to print. * @param indent * The level of indentation, can be NULL */ void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj, char *indent); /** * Calculates the unique public field. The unique public field is the digest, based on name algorithm * of the key + protection seed (concatenated). * * @param namealg * The name algorithm of the object, from the public portion. * @param key * The key bytes themselves. It seems odd that the type is TPM2B_PRIVATE_VENDOR_SPECIFIC * but this for access to the ANY field. * @param seed * The seed, from the sensitive portion. * @param unique * The result, a generated unique value for the public portion. * @return * True on success, false otherwise. */ bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg, TPM2B_PRIVATE_VENDOR_SPECIFIC *key, TPM2B_DIGEST *seed, TPM2B_DIGEST *unique); /** * Uses TR_FromTPMPublic() to construct the ESYS_TR object corresponding * to the passed TPM2_HANDLE. * @param context * an ESAPI context * @param sys_handle * the TPM2_HANDLE to construct an ESYS_TR handle for * @param esys_handle * pointer to an ESYS_TR handle to output the found handle into * @return * A tool_rc indicating status. */ tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context, TPM2_HANDLE sys_handle, ESYS_TR *esys_handle); /** * Map a TPMI_RH_PROVISION to the corresponding ESYS_TR constant * @param inh * The hierarchy to map */ ESYS_TR tpm2_tpmi_hierarchy_to_esys_tr(TPMI_RH_PROVISION inh); char *tpm2_util_getenv(const char *name); typedef enum tpm2_handle_flags tpm2_handle_flags; enum tpm2_handle_flags { TPM2_HANDLE_FLAGS_NONE = 0, TPM2_HANDLE_FLAGS_O = 1 << 0, TPM2_HANDLE_FLAGS_P = 1 << 1, TPM2_HANDLE_FLAGS_E = 1 << 2, TPM2_HANDLE_FLAGS_N = 1 << 3, TPM2_HANDLE_FLAGS_L = 1 << 4, TPM2_HANDLE_FLAGS_ALL_HIERACHIES = 0x1F, TPM2_HANDLES_FLAGS_TRANSIENT = 1 << 5, TPM2_HANDLES_FLAGS_PERSISTENT = 1 << 6, /* bits 7 and 8 are mutually exclusive */ TPM2_HANDLE_FLAGS_NV = 1 << 7, TPM2_HANDLE_ALL_W_NV = 0xFF, TPM2_HANDLE_FLAGS_PCR = 1 << 8, TPM2_HANDLE_ALL_W_PCR = 0x17F, }; /** * Converts an option from the command line into a valid TPM handle, checking * for errors and if the tool supports it based on flags settings. * @param value * The command line value to convert. * @param handle * The output handle. * @param flags * The flags indicating what is supported by the tool. * @return * true on success, false otherwise. */ bool tpm2_util_handle_from_optarg(const char *value, TPMI_RH_PROVISION *hierarchy, tpm2_handle_flags flags); bool tpm2_util_get_label(const char *value, TPM2B_DATA *label); /** * Prints a TPMS_TIME_INFO in a YAML compliant format to stdout. * @param current_time * The time structure to print */ void tpm2_util_print_time(const TPMS_TIME_INFO *current_time); /** * Given the parent qualified name and the name of an object, computes * that objects qualified name. * * The qualified name is defined as: * QNB ≔ HB (QNA || NAMEB) * * Where: * - QNB is the qualified name of the object. * - HB is the name hash algorithm of the object. * - QNA is the qualified name of the parent object. * - NAMEB is the name of the object. * * @param pqname * The parent qualified name. * @param halg * The name hash algorithm of the object. * @param name * The name of the object. * @param qname * The output qname, valid on success. * @return * True on success, false otherwise. */ bool tpm2_calq_qname(TPM2B_NAME *pqname, TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname); /** * Reads safely from stdin. * * @param length * Maximum length to read. * @param data * The output data that was read, valid on success. * @return * True on success, false otherwise. */ bool tpm2_safe_read_from_stdin(int length, char *data); /** * Converts a PEM-encoded public key to its sha256 representation (fingerprint). * The resulting Base64-encoded fingerprint format is based on the SSH: * ''' * ssh-keygen -lf id_ecdsa.pub * 256 SHA256:wTUOtZnoSGKwq36mPIN20rCK0Fc1y0zCvHxI2eAvVxU * ''' * * @param pem_encoded_key * The PEM-encoded public key. * @param fingerprint * The resulting fingerprint, valid on success. * @return * True on success, false otherwise. */ bool tpm2_pem_encoded_key_to_fingerprint(const char* pem_encoded_key, char* fingerprint); /** * Restores session handles to be used as auxilary sessions in addition to the * possible authorization sessions with a command. * * @param ectx * The ESAPI context * @param session_cnt * Total number of sessions to restore * @param session_path * An array of string data specifying the individual session file path * @param session_handle * An array of session handles updated as a result resuming sessions * @param session * An array of session structures updated as a result of resuming sessions * @return * Success: tool_rc_success, Faiure: tool_rc_general_error */ tool_rc tpm2_util_aux_sessions_setup( ESYS_CONTEXT *ectx, uint8_t session_cnt, const char **session_path, ESYS_TR *session_handle, tpm2_session **session); TPMI_ALG_HASH tpm2_util_calculate_phash_algorithm(ESYS_CONTEXT *ectx, const char **cphash_path, TPM2B_DIGEST *cp_hash, const char **rphash_path, TPM2B_DIGEST *rp_hash, tpm2_session **sessions); #endif /* STRING_BYTES_H */ tpm2-tools-5.2/man/000077500000000000000000000000001412464516500141635ustar00rootroot00000000000000tpm2-tools-5.2/man/.gitignore000066400000000000000000000000141412464516500161460ustar00rootroot00000000000000man8/ man1/ tpm2-tools-5.2/man/common/000077500000000000000000000000001412464516500154535ustar00rootroot00000000000000tpm2-tools-5.2/man/common/alg.md000066400000000000000000000067271412464516500165540ustar00rootroot00000000000000# Algorithm Specifiers Options that take algorithms support "nice-names". There are two major algorithm specification string classes, simple and complex. Only certain algorithms will be accepted by the TPM, based on usage and conditions. ## Simple specifiers These are strings with no additional specification data. When creating objects, non-specified portions of an object are assumed to defaults. You can find the list of known "Simple Specifiers Below". ### Asymmetric * rsa * ecc ### Symmetric * aes * camellia ### Hashing Algorithms * sha1 * sha256 * sha384 * sha512 * sm3_256 * sha3_256 * sha3_384 * sha3_512 ### Keyed Hash * hmac * xor ### Signing Schemes * rsassa * rsapss * ecdsa * ecdaa * ecschnorr ### Asymmetric Encryption Schemes * oaep * rsaes * ecdh ### Modes * ctr * ofb * cbc * cfb * ecb ### Misc * null ## Complex Specifiers Objects, when specified for creation by the TPM, have numerous algorithms to populate in the public data. Things like type, scheme and asymmetric details, key size, etc. Below is the general format for specifying this data: `::` ### Type Specifiers This portion of the complex algorithm specifier is required. The remaining scheme and symmetric details will default based on the type specified and the type of the object being created. * aes - Default AES: aes128 * aes128`` - 128 bit AES with optional mode (*ctr*|*ofb*|*cbc*|*cfb*|*ecb*). If mode is not specified, defaults to *null*. * aes192`` - Same as aes128``, except for a 192 bit key size. * aes256`` - Same as aes128``, except for a 256 bit key size. * ecc - Elliptical Curve, defaults to ecc256. * ecc192 - 192 bit ECC * ecc224 - 224 bit ECC * ecc256 - 256 bit ECC * ecc384 - 384 bit ECC * ecc521 - 521 bit ECC * rsa - Default RSA: rsa2048 * rsa1024 - RSA with 1024 bit keysize. * rsa2048 - RSA with 2048 bit keysize. * rsa4096 - RSA with 4096 bit keysize. ### Scheme Specifiers Next, is an optional field, it can be skipped. Schemes are usually **Signing Schemes** or **Asymmetric Encryption Schemes**. Most signing schemes take a hash algorithm directly following the signing scheme. If the hash algorithm is missing, it defaults to *sha256*. Some take no arguments, and some take multiple arguments. #### Hash Optional Scheme Specifiers These scheme specifiers are followed by a dash and a valid hash algorithm, For example: `oaep-sha256`. * oaep * ecdh * rsassa * rsapss * ecdsa * ecschnorr #### Multiple Option Scheme Specifiers This scheme specifier is followed by a count (max size UINT16) then followed by a dash(-) and a valid hash algorithm. * ecdaa For example, ecdaa4-sha256. If no count is specified, it defaults to 4. #### No Option Scheme Specifiers This scheme specifier takes NO arguments. * rsaes ### Symmetric Details Specifiers This field is optional, and defaults based on the *type* of object being created and it's attributes. Generally, any valid **Symmetric** specifier from the **Type Specifiers** list should work. If not specified, an asymmetric objects symmetric details defaults to *aes128cfb*. ## Examples ### Create an rsa2048 key with an rsaes asymmetric encryption scheme `tpm2_create -C parent.ctx -G rsa2048:rsaes -u key.pub -r key.priv` ### Create an ecc256 key with an ecdaa signing scheme with a count of 4 and sha384 hash `/tpm2_create -C parent.ctx -G ecc256:ecdaa4-sha384 -u key.pub -r key.priv` tpm2-tools-5.2/man/common/authorizations.md000066400000000000000000000052451412464516500210660ustar00rootroot00000000000000# Authorization Formatting Authorization for use of an object in TPM2.0 can come in 3 different forms: 1. Password 2. HMAC 3. Sessions **NOTE:** "Authorizations default to the **EMPTY PASSWORD** when not specified". ## Passwords Passwords are interpreted in the following forms below using prefix identifiers. **Note**: By default passwords are assumed to be in the string form when they do not have a prefix. ### String A string password, specified by prefix "str:" or it's absence (raw string without prefix) is not interpreted, and is directly used for authorization. #### Examples ``` foobar str:foobar ``` ### Hex-string A hex-string password, specified by prefix "hex:" is converted from a hexidecimal form into a byte array form, thus allowing passwords with non-printable and/or terminal un-friendly characters. #### Example ``` hex:0x1122334455667788 ``` ### File A file based password, specified be prefix "file:" should be the path of a file containing the password to be read by the tool or a "-" to use stdin. Storing passwords in files prevents information leakage, passwords passed as options can be read from the process list or common shell history features. #### Examples ``` # to use stdin and be prompted file:- # to use a file from a path file:path/to/password/file # to echo a password via stdin: echo foobar | tpm2_tool -p file:- # to use a bash here-string via stdin: tpm2_tool -p file:- <<< foobar ``` ## Sessions When using a policy session to authorize the use of an object, prefix the option argument with the *session* keyword. Then indicate a path to a session file that was created with tpm2_startauthsession(1). Optionally, if the session requires an auth value to be sent with the session handle (eg policy password), then append a + and a string as described in the **Passwords** section. ### Examples To use a session context file called *session.ctx*. ``` session:session.ctx ``` To use a session context file called *session.ctx* **AND** send the authvalue mypassword. ``` session:session.ctx+mypassword ``` To use a session context file called *session.ctx* **AND** send the *HEX* authvalue 0x11223344. ``` session:session.ctx+hex:11223344 ``` ## PCR Authorizations You can satisfy a PCR policy using the "pcr:" prefix and the PCR minilanguage. The PCR minilanguage is as follows: `=` The PCR spec is documented in in the section "PCR bank specifiers". The `raw-pcr-file` is an **optional** argument that contains the output of the raw PCR contents as returned by *tpm2_pcrread(1)*. [PCR bank specifiers](pcr.md) ### Examples To satisfy a PCR policy of sha256 on banks 0, 1, 2 and 3 use a specifier of: ``` pcr:sha256:0,1,2,3 ``` tpm2-tools-5.2/man/common/ctxobj.md000066400000000000000000000011221412464516500172620ustar00rootroot00000000000000# Context Object Format The type of a context object, whether it is a handle or file name, is determined according to the following logic *in-order*: * If the argument is a file path, then the file is loaded as a restored TPM transient object. * If the argument is a *prefix* match on one of: * owner: the owner hierarchy * platform: the platform hierarchy * endorsement: the endorsement hierarchy * lockout: the lockout control persistent object * If the argument argument can be loaded as a number it will be treat as a handle, e.g. 0x81010013 and used directly.tpm2-tools-5.2/man/common/footer.md000066400000000000000000000002301412464516500172660ustar00rootroot00000000000000# BUGS [Github Issues](https://github.com/tpm2-software/tpm2-tools/issues) # HELP See the [Mailing List](https://lists.01.org/mailman/listinfo/tpm2) tpm2-tools-5.2/man/common/hash.md000066400000000000000000000005631412464516500167240ustar00rootroot00000000000000# Supported Hash Algorithms Supported hash algorithms are: * **0x4** or **sha1** for **TPM_ALG_SHA1** * **0xB** or **sha256** for **TPM_ALG_SHA256** **(default)** * **0xC** or **sha384** for **TPM_ALG_SHA384** * **0xD** or **sha512** for **TPM_ALG_SHA512** * **0x12** or **sm3_256** for **TPM_ALG_SM3_256** **NOTE**: Your TPM may not support all algorithms. tpm2-tools-5.2/man/common/nv-attrs.md000066400000000000000000000037031412464516500175560ustar00rootroot00000000000000# NV Attributes NV Attributes are used to control various properties of the NV defined space. When specified as an option, either the raw bitfield mask or "nice-names" may be used. The values can be found in Table 204 Part 2 of the TPM2.0 specification, which can be found here: Nice names are calculated by taking the name field of table 204 and removing the prefix **TPMA_NV_** and lowercasing the result. Thus, **TPMA_NV_PPWRITE** becomes ppwrite. Nice names can be joined using the bitwise or "|" symbol. Note that the **TPM_NT** field is 4 bits wide, and thus can be set via **nt=** format. For instance, to set The fields **TPMA_NV_OWNERREAD**, **TPMA_NV_OWNERWRITE**, **TPMA_NV_POLICYWRITE**, and **TPMA_NT = 0x2**, the argument would be: **ownerread|ownerwrite|policywrite|nt=0x2** Additionally, the NT field, which denotes the type of the NV index, can also be specified via friendly names: * ordinary - Ordinary contains data that is opaque to the TPM that can only be modified using TPM2\_NV\_Write. * extend - Extend is used similarly to a PCR and can only be modified with TPM2_NV_Extend. Its size is determined by the length of the hash algorithm used. * counter - Counter contains an 8-octet value that is to be used as a counter and can only be modified with TPM2\_NV\_Increment * bits - Bit Field contains an 8-octet value to be used as a bit field and can only be modified with TPM2\_NV\_SetBits. * pinfail - PIN Fail contains an 8-octet pinCount that increments on a PIN authorization failure and a pinLimit. * pinpass - PIN Pass contains an 8-octet pinCount that increments on a PIN authorization success and a pinLimit. For instance, to set The fields **TPMA_NV_OWNERREAD**, **TPMA_NV_OWNERWRITE**, **TPMA_NV_POLICYWRITE**, and **TPMA_NT = bits**, the argument would be: **ownerread|ownerwrite|policywrite|nt=bits** tpm2-tools-5.2/man/common/obj-attrs.md000066400000000000000000000014141412464516500177020ustar00rootroot00000000000000# Object Attributes Object Attributes are used to control various properties of created objects. When specified as an option, either the raw bitfield mask or "nice-names" may be used. The values can be found in Table 31 Part 2 of the TPM2.0 specification, which can be found here: Nice names are calculated by taking the name field of table 31 and removing the prefix **TPMA_OBJECT_** and lowercasing the result. Thus, **TPMA_OBJECT_FIXEDTPM** becomes fixedtpm. Nice names can be joined using the bitwise or "|" symbol. For instance, to set The fields **TPMA_OBJECT_FIXEDTPM**, **TPMA_OBJECT_NODA**, and **TPMA_OBJECT_SIGN_ENCRYPT**, the argument would be: **fixedtpm|noda|sign** tpm2-tools-5.2/man/common/object-alg.md000066400000000000000000000112321412464516500200030ustar00rootroot00000000000000# Supported Public Object Algorithms Supported public object algorithms are: ## Symmetric ### AES The AES cipher has a bitsize and a mode. When the mode is not specified, ie a "NULL" mode, the TPM will allow any mode usages on subsequent key uses. If the mode is specified during object creation, only that mode is allowed in subsequent use cases. * **aes** - Default AES selection. The default AES Selection is AES 128 with a NULL mode. * **aes[128|192|256]** - AES with a key size of 128, 192 and 256 respectively with a NULL mode. * **aes[128|192|256][cbc|ocb|cfb|ecb]** - AES with a key size of 128, 192 and 256 and a mode of cbc, ocb, cfb and ecb respectively. #### Examples * aes256cbc - AES with a key bitsize of 256 and a mode of cbc. * aes192cfb - AES with a bitsize of 192 and mode of cfb. * aes128 - AES with a bitsize of 128 and NULL mode. ## Asymmetric ### RSA The RSA cipher has a bitsize, and the TPM (optionally) supports associating a symmetric key along with the RSA algorithm. The AES key will be used for encryption modes that rely on an RSA scheme, like RSAES_OAEP. * **rsa** - Default RSA algorithm. The default bitsize is 2048. Depending on if the object is a restricted object (aka a parent object), the algorithms encryption options will default to: * restricted object - scheme of null and a NULL symmetric algorithm. * non-restricted object - scheme of null and an aes128cfb symmetric algorithm. * **rsa[1024|2048|4096]** - Similar to **rsa** option, but provides control over the key size to either 1024, 2048 or 4096 respectively. * **rsa[1024|2048|4096]:[oaep|rsaes]** - Similar to **rsa[1024|2048|4096]** option, but provides the ability to control the scheme. The algorithms encryption options will default to: aes128cfb. * **rsa[1024|2048|4096]:[oaep|rsaes]:[aes]** Similar to **rsa[1024|2048]:[oaep|rsaes]** option, but provides full control over the aes key options. See the section **AES** for details of these AES strings. #### Examples * rsa1024 - Creates an RSA 1024 key with a scheme and symmetric algorithm dependent on the restricted attribute. * rsa:oeap:aes - Creates an RSA 2048 key with an AES-OEAP scheme and an AES default key based on attributes. * rsa1024:null:aes128cbc - Creates an RSA 1024 key with a NULL encryption scheme and an AES key of 128 for use ONLY with CBC. ### ECC The ECC cipher has a size, and the TPM (optionally) supports associating a symmetric key along with the ECC algorithm. The AES key will be used for encryption modes that rely on an asymmetric encryption scheme, like RSAES_OAEP. * **ecc** - Default ECC algorithm. The default curve size is 256. Depending on if the object is a restricted object (aka a parent object), the algorithms encryption options will default to: * restricted object - scheme of null and a NULL symmetric algorithm. * non-restricted object - scheme of null and an aes128cfb symmetric algorithm. * **ecc[224|256|384|521]** - Similar to **ecc** option, but provides control over the curve size to either 224,256,384 or 521 respectively. * **ecc[224|256|384|521]:[oaep|rsaes]** - Similar to **ecc[224|256|384|521]** option, but provides the ability to control the scheme. The algorithms encryption options will default to: aes128cfb. * **ecc[224|256|384|521]:[oaep|rsaes]:[aes]** Similar to **ecc[224|256|384|521]:[oaep|rsaes]** option, but provides full control over the aes key options. See the section **AES** for details of these AES strings. #### Examples * ecc224 - Creates an ECC 224 key with a scheme and symmetric algorithm dependent on the restricted attribute. * ecc:oeap:aes - Creates an ECC 256 key with an AES-OEAP scheme and an AES default key based on attributes. * ecc384:null:aes128cbc - Creates an ECC 384 key with a NULL encryption scheme and an AES key of 128 for use ONLY with CBC. ## KeyedHash The keyedhash algorithms are hmac and xor. ### HMAC The HMAC algorithm needs a hashing algorithm and nothing more. It defaults to sha256 if not specified. * **hmac:[sha256|sha384|sha512]** - Generate an HMAC key valid for the associated hash algorithm, defaults to sha256 if not specified. ### XOR The XOR algorithm needs a hashing algorithm and nothing more. It defaults to sha256 if not specified. The XOR scheme should be used where confidentiality of the objects is desired, but secrecy is not mandatory. The algorithm is lightweight and quick. * **xor:[sha256|sha384|sha512]** - Generate an XOR key valid for the associated hash algorithm, defaults to sha256 if not specified. **NOTE**: Your TPM may not support all algorithms. tpm2-tools-5.2/man/common/options.md000066400000000000000000000024271412464516500174750ustar00rootroot00000000000000# COMMON OPTIONS This collection of options are common to many programs and provide information that many users may expect. * **-h**, **\--help=[man|no-man]**: Display the tools manpage. By default, it attempts to invoke the manpager for the tool, however, on failure will output a short tool summary. This is the same behavior if the "man" option argument is specified, however if explicit "man" is requested, the tool will provide errors from man on stderr. If the "no-man" option if specified, or the manpager fails, the short options will be output to stdout. To successfully use the manpages feature requires the manpages to be installed or on _MANPATH_, See man(1) for more details. * **-v**, **\--version**: Display version information for this tool, supported tctis and exit. * **-V**, **\--verbose**: Increase the information that the tool prints to the console during its execution. When using this option the file and line number are printed. * **-Q**, **\--quiet**: Silence normal tool output to stdout. * **-Z**, **\--enable-errata**: Enable the application of errata fixups. Useful if an errata fixup needs to be applied to commands sent to the TPM. Defining the environment TPM2TOOLS\_ENABLE\_ERRATA is equivalent. tpm2-tools-5.2/man/common/pcr.md000066400000000000000000000007011412464516500165570ustar00rootroot00000000000000# PCR Bank Specifiers PCR Bank Selection lists follow the below specification: ``` :[,] or :all ``` multiple banks may be separated by '+'. For example: ``` sha1:3,4+sha256:all ``` will select PCRs 3 and 4 from the SHA1 bank and PCRs 0 to 23 from the SHA256 bank. ## Note PCR Selections allow for up to 5 hash to pcr selection mappings. This is a limitation in design in the single call to the tpm to get the pcr values. tpm2-tools-5.2/man/common/pcrs_format.md000066400000000000000000000004461412464516500203200ustar00rootroot00000000000000 * **-F**, **\--pcrs_format**=_FORMAT_: Format selection for the binary blob in the PCR output file. 'values' will output a binary blob of the PCR values. 'serialized' will output a binary blob of the PCR values in the form of serialized data structure in little endian format. Optional. tpm2-tools-5.2/man/common/policy-limitations.md000066400000000000000000000004571412464516500216340ustar00rootroot00000000000000# Limitations It expects a session to be already established via **tpm2_startauthsession**(1) and requires one of the following: - direct device access - extended session support with **tpm2-abrmd**. Without it, most resource managers **will not** save session state between command invocations. tpm2-tools-5.2/man/common/protection-details.md000066400000000000000000000016471412464516500216160ustar00rootroot00000000000000# Protection Details Objects that can move outside of TPM need to be protected (confidentiality and integrity). For instance, transient objects require that TPM protected data (key or seal material) be stored outside of the TPM. This is seen in tools like tpm2\_create(1), where the **-r** option outputs this protected data. This blob contains the sensitive portions of the object. The sensitive portions of the object are protected by the parent object, using the parent's symmetric encryption details to encrypt the sensitive data and HMAC it. In-depth details can be found in sections 23 of: - https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf Notably Figure 20, is relevant, even though it's specifically referring to duplication blobs, the process is identical. If the output is from tpm2\_duplicate(1), the output will be slightly different, as described fully in section 23. tpm2-tools-5.2/man/common/pubkey.md000066400000000000000000000006171412464516500173000ustar00rootroot00000000000000 * **-f**, **\--format**: Format selection for the public key output file. 'tss' (the default) will output a binary blob according to the TPM 2.0 Specification. 'pem' will output an OpenSSL compatible PEM encoded public key. 'der' will output an OpenSSL compatible DER encoded public key. 'tpmt' will output a binary blob of the TPMT_PUBLIC struct referenced by TPM 2.0 specs. tpm2-tools-5.2/man/common/returns.md000066400000000000000000000004051412464516500174760ustar00rootroot00000000000000# Returns Tools can return any of the following codes: - 0 - Success. - 1 - General non-specific error. - 2 - Options handling error. - 3 - Authentication error. - 4 - TCTI related error. - 5 - Non supported scheme. Applicable to tpm2_testparams. tpm2-tools-5.2/man/common/signature.md000066400000000000000000000004641412464516500200020ustar00rootroot00000000000000# Signature Format Specifiers Format selection for the signature output file. **tss** (the default) will output a binary blob according to the TPM 2.0 specification and any potential compiler padding. The option **plain** will output the plain signature data as defined by the used cryptographic algorithm. tpm2-tools-5.2/man/common/signschemes.md000066400000000000000000000005441412464516500203100ustar00rootroot00000000000000# Supported Signing Schemes Supported signing algorithms are: * **0x5** or **hmac** for **TPM_ALG_HMAC** * **0x14** or **rsassa** for **TPM_ALG_RSASSA** * **0x15** or **rsaes** for **TPM_ALG_RSAES** * **0x16** or **rsapss** for **TPM_ALG_RSAPSS** * **0x17** or **oeap** for **TPM_ALG_OAEP** **NOTE**: Your TPM may not support all algorithms. tpm2-tools-5.2/man/common/tcti.md000066400000000000000000000067231412464516500167500ustar00rootroot00000000000000# TCTI Configuration The TCTI or "Transmission Interface" is the communication mechanism with the TPM. TCTIs can be changed for communication with TPMs across different mediums. To control the TCTI, the tools respect: 1. The command line option **-T** or **\--tcti** 2. The environment variable: _TPM2TOOLS\_TCTI_. **Note:** The command line option always overrides the environment variable. The current known TCTIs are: * tabrmd - The resource manager, called [tabrmd](https://github.com/tpm2-software/tpm2-abrmd). Note that tabrmd and abrmd as a tcti name are synonymous. * mssim - Typically used for communicating to the TPM software simulator. * device - Used when talking directly to a TPM device file. * none - Do not initalize a connection with the TPM. Some tools allow for off-tpm options and thus support not using a TCTI. Tools that do not support it will error when attempted to be used without a TCTI connection. Does not support *ANY* options and *MUST BE* presented as the exact text of "none". The arguments to either the command line option or the environment variable are in the form: `:` Specifying an empty string for either the `` or `` results in the default being used for that portion respectively. ## TCTI Defaults When a TCTI is not specified, the default TCTI is searched for using *dlopen(3)* semantics. The tools will search for *tabrmd*, *device* and *mssim* TCTIs **IN THAT ORDER** and **USE THE FIRST ONE FOUND**. You can query what TCTI will be chosen as the default by using the **-v** option to print the version information. The "default-tcti" key-value pair will indicate which of the aforementioned TCTIs is the default. ## Custom TCTIs Any TCTI that implements the dynamic TCTI interface can be loaded. The tools internally use *dlopen(3)*, and the raw *tcti-name* value is used for the lookup. Thus, this could be a path to the shared library, or a library name as understood by *dlopen(3)* semantics. # TCTI OPTIONS This collection of options are used to configure the various known TCTI modules available: * **device**: For the device TCTI, the TPM character device file for use by the device TCTI can be specified. The default is */dev/tpm0*. Example: **-T device:/dev/tpm0** or **export _TPM2TOOLS\_TCTI_="device:/dev/tpm0"** * **mssim**: For the mssim TCTI, the domain name or IP address and port number used by the simulator can be specified. The default are 127.0.0.1 and 2321. Example: **-T mssim:host=localhost,port=2321** or **export _TPM2TOOLS\_TCTI_="mssim:host=localhost,port=2321"** * **abrmd**: For the abrmd TCTI, the configuration string format is a series of simple key value pairs separated by a ',' character. Each key and value string are separated by a '=' character. * TCTI abrmd supports two keys: 1. 'bus_name' : The name of the tabrmd service on the bus (a string). 2. 'bus_type' : The type of the dbus instance (a string) limited to 'session' and 'system'. Specify the tabrmd tcti name and a config string of ```bus_name=com.example.FooBar```: ``` \--tcti=tabrmd:bus_name=com.example.FooBar ``` Specify the default (abrmd) tcti and a config string of ```bus_type=session```: ``` \--tcti:bus_type=session ``` **NOTE**: abrmd and tabrmd are synonymous. tpm2-tools-5.2/man/common/tss2-fapi-references.md000066400000000000000000000006151412464516500217260ustar00rootroot00000000000000# SEE ALSO **fapi-config(5)** to adjust Fapi parameters like the used cryptographic profile and TCTI or directories for the Fapi metadata storages. **fapi-profile(5)** to determine the cryptographic algorithms and parameters for all keys and operations of a specific TPM interaction like the name hash algorithm, the asymmetric signature algorithm, scheme and parameters and PCR bank selection. tpm2-tools-5.2/man/common/tss2-options.md000066400000000000000000000015001412464516500203550ustar00rootroot00000000000000# COMMON OPTIONS This collection of options are common to all tss2 programs and provide information that many users may expect. * **-h**, **\--help [man|no-man]**: Display the tools manpage. By default, it attempts to invoke the manpager for the tool, however, on failure will output a short tool summary. This is the same behavior if the "man" option argument is specified, however if explicit "man" is requested, the tool will provide errors from man on stderr. If the "no-man" option if specified, or the manpager fails, the short options will be output to stdout. To successfully use the manpages feature requires the manpages to be installed or on _MANPATH_, See **man**(1) for more details. * **-v**, **\--version**: Display version information for this tool, supported tctis and exit. tpm2-tools-5.2/man/tpm2.1.md000066400000000000000000000063461412464516500155370ustar00rootroot00000000000000% tpm2(1) tpm2-tools | General Commands Manual # NAME **tpm2**(1) - A single small executable that combines the various tpm2-tools much like a BusyBox that provides a fairly complete environment for any small or embedded system. # SYNOPSIS **tpm2** [*OPTIONS*] [*ARGUMENTS*] # DESCRIPTION **tpm2**(1) - To ease installation of tpm2-tools in initrd or embedded systems where size-optimization and limited resources are important, it is convenient to have a single executable that can dispatch the various TPM2 functionalities specified by the argument which is one of the available tool names. The options and arguments that follow are either the **common options** or those specific to the **tool name**. It is important to note that individual tools with prefix **tpm2_** can still be invoked, however, they are now soft-linked to this **tpm2** executable. And so unlike BusyBox, full functionality of the individual tools is available in the executable. For example: **tpm2_getrandom 8** can alternatively be specified as **tpm2 getrandom 8**. # ARGUMENTS List of possible tool names. NOTE: Specify only one of these. Look at examples. **certifyX509certutil** **checkquote** **eventlog** **print** **rc_decode** **activatecredential** **certify** **changeauth** **changeeps** **changepps** **clear** **clearcontrol** **clockrateadjust** **create** **createak** **createek** **createpolicy** **setprimarypolicy** **createprimary** **dictionarylockout** **duplicate** **getcap** **gettestresult** **encryptdecrypt** **evictcontrol** **flushcontext** **getekcertificate** **getrandom** **gettime** **hash** **hierarchycontrol** **hmac** **import** **incrementalselftest** **load** **loadexternal** **makecredential** **nvdefine** **nvextend** **nvincrement** **nvreadpublic** **nvread** **nvreadlock** **nvundefine** **nvwrite** **nvwritelock** **nvsetbits** **pcrallocate** **pcrevent** **pcrextend** **pcrread** **pcrreset** **policypcr** **policyauthorize** **policyauthorizenv** **policynv** **policycountertimer** **policyor** **policynamehash** **policytemplate** **policycphash** **policypassword** **policysigned** **policyticket** **policyauthvalue** **policysecret** **policyrestart** **policycommandcode** **policynvwritten** **policyduplicationselect** **policylocality** **quote** **readclock** **readpublic** **rsadecrypt** **rsaencrypt** **send** **selftest** **sessionconfig** **setclock** **shutdown** **sign** **certifycreation** **nvcertify** **startauthsession** **startup** **stirrandom** **testparms** **unseal** **verifysignature** **setcommandauditstatus** **getcommandauditdigest** **getsessionauditdigest** **geteccparameters** **ecephemeral** **commit** **ecdhkeygen** **ecdhzgen** **zgen2phase** ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Get 8 rand bytes from the TPM ```bash tpm2 getrandom 8 | xxd -p ``` ## Send a TPM Startup Command with flags TPM2\_SU\_CLEAR ```bash tpm2 startup -c ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_activatecredential.1.md000066400000000000000000000057571412464516500214570ustar00rootroot00000000000000% tpm2_activatecredential(1) tpm2-tools | General Commands Manual # NAME **tpm2_activatecredential**(1) - Enables access to the credential qualifier to recover the credential secret. # SYNOPSIS **tpm2_activatecredential** [*OPTIONS*] # DESCRIPTION **tpm2_activatecredential**(1) - Enables the association of a credential with an object in a way that ensures that the TPM has validated the parameters of the credentialed object. In an attestation scheme , this guarantees the registrar that the attestation key belongs to the TPM with a qualified parent key in the TPM. # OPTIONS * **-c**, **\--credentialedkey-context**=_OBJECT_: Object associated with the created certificate by CA. * **-C**, **\--credentialkey-context**=_OBJECT_: The loaded object used to decrypt the random seed. * **-p**, **\--credentialedkey-auth**=_AUTH_: The auth value of the credentialed object specified with **-c**. * **-P**, **\--credentialkey-auth**=_AUTH_: The auth value of the credential object specified with **-C**. * **-i**, **\--credential-blob**=_FILE_: The input file path containing the credential blob and secret created with the **tpm2_makecredential**(1) tool. * **-o**, **\--certinfo-data**=_FILE_: The output file path to save the decrypted credential secret information. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash echo "12345678" > secret.data tpm2_createek -Q -c 0x81010001 -G rsa -u ek.pub tpm2_createak -C 0x81010001 -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \ -n ak.name -p akpass> ak.out file_size=`stat --printf="%s" ak.name` loaded_key_name=`cat ak.name | xxd -p -c $file_size` tpm2_makecredential -Q -e ek.pub -s secret.data -n $loaded_key_name \ -o mkcred.out tpm2_startauthsession --policy-session -S session.ctx tpm2_policysecret -S session.ctx -c e tpm2_activatecredential -Q -c ak.ctx -C 0x81010001 -i mkcred.out \ -o actcred.out -p akpass -P"session:session.ctx" tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_certify.1.md000066400000000000000000000061741412464516500172630ustar00rootroot00000000000000% tpm2_certify(1) tpm2-tools | General Commands Manual # NAME **tpm2_certify**(1) - Prove that an object is loaded in the TPM. # SYNOPSIS **tpm2_certify** [*OPTIONS*] # DESCRIPTION **tpm2_certify**(1) - Proves that an object with a specific _NAME_ is loaded in the TPM. By certifying that the object is loaded, the TPM warrants that a public area with a given _NAME_ is self-consistent and associated with a valid sensitive area. If a relying party has a public area that has the same _NAME_ as a _NAME_ certified with this command, then the values in that public area are correct. An object that only has its public area loaded cannot be certified. # OPTIONS These options control the certification: * **-c**, **\--certifiedkey-context**=_OBJECT_: The object to be certified. * **-C**, **\--signingkey-context**=_OBJECT_: The key used to sign the attestation structure. * **-p**, **\--certifiedkey-auth**=_AUTH_: The authorization value provided for the object specified with -c. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm to use in signature generation. * **-P**, **\--signingkey-auth**=_AUTH_: The authorization value for the signing key specified with -C. * **-o**, **\--attestation**=_FILE_: Output file name for the attestation data. * **-s**, **\--signature**=_FILE_: Output file name for the signature data. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Create a primary key and certify it with a signing key. ```bash tpm2_createprimary -Q -C e -g sha256 -G rsa -c primary.ctx tpm2_create -Q -g sha256 -G rsa -u certify.pub -r certify.priv -C primary.ctx tpm2_load -Q -C primary.ctx -u certify.pub -r certify.priv -n certify.name \ -c certify.ctx tpm2_certify -Q -c primary.ctx -C certify.ctx -g sha256 -o attest.out -s sig.out ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_certifyX509certutil.1.md000066400000000000000000000040221412464516500214130ustar00rootroot00000000000000% tpm2_certifyX509certutil(1) tpm2-tools | General Commands Manual # NAME **tpm2_certifyX509certutil**(1) - Generate partial X509 certificate. # SYNOPSIS **tpm2_certifyX509certutil** [*OPTIONS*] # DESCRIPTION **tpm2_certifyX509certutil**(1) - Generates a partial certificate that is suitable as the third input parameter for TPM2_certifyX509 command. The certificate data is written into a file in DER format and can be examined using openssl asn1parse tool as follows: ```bash openssl asn1parse -in partial_cert.der -inform DER ``` # OPTIONS These are the available options: * **-o**, **\--outcert**=_STRING_: The output file where the certificate will be written to. The default is partial_cert.der Optional parameter. * **-d**, **\--days**=_NUMBER_: The number of days the certificate will be valid starting from today. The default is 3560 (10 years) Optional parameter. * **-i**, **\--issuer**=_STRING_: The ISSUER entry for the cert in the following format: --issuer="C=US;O=org;OU=Org unit;CN=cname" Supported fields are: * C - "Country", max size = 2 * O - "Org", max size = 8 * OU - "Org Unit", max size = 8 * CN - "Common Name", max size = 8 The files need to be separated with semicolon. At list one supported field is required for the option to be valid. Optional parameter. * **-s**, **\--subject**=_STRING_: The SUBJECT for the cert in the following format: --subject="C=US;O=org;OU=Org unit;CN=cname" Supported fields are: * C - "Country", max size = 2 * O - "Org", max size = 8 * OU - "Org Unit", max size = 8 * CN - "Common Name", max size = 8 The files need to be separated with semicolon. At list one supported field is required for the option to be valid. Optional parameter. * **ARGUMENT** No arguments required. ## References [common options](common/options.md) collection of common options that provide information many users may expect. # EXAMPLES ```bash tpm2 certifyX509certutil -o partial_cert.der -d 356 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_certifycreation.1.md000066400000000000000000000066541412464516500210130ustar00rootroot00000000000000% tpm2_certifycreation(1) tpm2-tools | General Commands Manual # NAME **tpm2_certifycreation**(1) - Attest the association between a loaded public area and the provided hash of the creation data. # SYNOPSIS **tpm2_certifycreation** [*OPTIONS*] # DESCRIPTION **tpm2_certifycreation**(1) - Attest the association between a loaded public area and the provided hash of the creation data. The creation data and the creation ticket is produced when creating the object. The object itself is created with either **TPM2_CreatePrimary** or **TPM2_Create** commands. # OPTIONS * **-C**, **\--signingkey-context**=_OBJECT_: Context object pointing to the key used that signs the attestation. * **-P**, **\--signingkey-auth**_AUTH_: Optional authorization value to use for the key specified by **-C**. * **-c**, **\--certifiedkey-context**=_OBJECT_: Context object pointing to the key that has to be certified. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the creation data. * **-s**, **\--scheme**=_ALGORITHM_: The signing scheme used to sign the attestation data. * **-d**, **\--creation-hash**=_FILE_ File containing the digest of the creation data. * **-t**, **\--ticket**=_FILE_: The ticket file to validate that the creation data was produced by the TPM. * **-o**, **\--signature**=_FILE_: File containing the signature of the attestation data for the certified key. * **-f**, **\--format**=_FORMAT_: Output signature format selection. * **--attestation**=_FILE_: The attestation data of the type TPM2_CREATION_INFO signed with signing key. * **-q**, **\--qualification**=_FILE\_OR\_HEX_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can either be a path or hex string. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [signature format specifiers](common/signature.md) # EXAMPLES ## Certify creation data of a primary key. ```bash tpm2_createprimary -C o -c prim.ctx --creation-data create.dat \ -d create.dig -t create.ticket tpm2_create -G rsa -u rsa.pub -r rsa.priv -C prim.ctx -c signing_key.ctx tpm2_certifycreation -C signing_key.ctx -c prim.ctx -d create.dig \ -t create.ticket -g sha256 -o sig.nature --attestation attestat.ion -f plain \ -s rsassa ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_changeauth.1.md000066400000000000000000000073001412464516500177150ustar00rootroot00000000000000% tpm2_changeauth(1) tpm2-tools | General Commands Manual # NAME **tpm2_changeauth** - Changes authorization values for TPM objects. # SYNOPSIS **tpm2_changeauth** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_changeauth** - Configures authorization values for the various hierarchies, NV indices, transient and persistent objects. Note: For non-permanent objects (Transient objects and Persistent objects), copies of the private information (files or persistent handles) created prior to changing auth are not invalidated. # OPTIONS Passwords should follow the "password authorization formatting standards", see section "Authorization Formatting". * **-c**, **\--object-context**=_OBJECT_: The key context object to be used for the operation. * **-p**, **\--object-auth**=_AUTH_: The old authorization value for the TPM object specified with **-c**. * **-C**, **\--parent-context**=_OBJECT_: The parent object. This is required if the object for the operation is a transient or persistent object. * **-r**, **\--private**=_FILE_: The output file which contains the new sensitive portion of the object whose auth was being changed. [protection details](common/protection-details.md) * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * **ARGUMENT** the command line argument specifies the _AUTH_ to be set for the object specified with **-c**. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set owner, endorsement and lockout authorizations to newpass ```bash tpm2_changeauth -c owner newpass tpm2_changeauth -c endorsement newpass tpm2_changeauth -c lockout newpass ``` ## Change owner, endorsement and lockout authorizations ```bash tpm2_changeauth -c o -p newpass newerpass tpm2_changeauth -c e -p newpass newerpass tpm2_changeauth -c l -p newpass newerpass ``` ## Set owner authorization to empty password ```bash tpm2_changeauth -c o -p oldpass ``` ## Modify authorization for a loadable transient object ```bash tpm2_createprimary -Q -C o -c prim.ctx tpm2_create -Q -g sha256 -G aes -u key.pub -r key.priv -C prim.ctx tpm2_load -C prim.ctx -u key.pub -r key.priv -n key.name -c key.ctx tpm2_changeauth -c key.ctx -C prim.ctx -r key.priv newkeyauth ``` ## Modify authorization for a NV Index Requires Extended Session Support. ```bash tpm2_startauthsession -S session.ctx tpm2_policycommandcode -S session.ctx -L policy.nvchange TPM2_CC_NV_ChangeAuth tpm2_flushcontext session.ctx NVIndex=0x1500015 tpm2_nvdefine $NVIndex -C o -s 32 -a "authread|authwrite" -L policy.nvchange tpm2_startauthsession \--policy-session -S session.ctx tpm2_policycommandcode -S session.ctx -L policy.nvchange TPM2_CC_NV_ChangeAuth tpm2_changeauth -p session:session.ctx -c $NVIndex newindexauth ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_changeeps.1.md000066400000000000000000000031231412464516500175420ustar00rootroot00000000000000% tpm2_changeeps(1) tpm2-tools | General Commands Manual # NAME **tpm2_changeeps**(1) - Replaces the active endorsement primary seed with a new one generated off the TPM2 RNG. # SYNOPSIS **tpm2_changeeps** [*OPTIONS*] # DESCRIPTION **tpm2_changeeps**(1) - Replaces the active endorsement primary seed with a new one generated off the TPM2 RNG. The Transient and Persistent objects under the endorsement hierarchy are lost. This command requires platform auth. # OPTIONS * **-p**, **\--auth**=_AUTH_ Specifies the _AUTH_ for the platform. hierarchy. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. ## References [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Change the endorsement primary seed where the platform auth is NULL. ```bash tpm2_changeeps ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_changepps.1.md000066400000000000000000000030641412464516500175610ustar00rootroot00000000000000% tpm2_changepps(1) tpm2-tools | General Commands Manual # NAME **tpm2_changepps**(1) - Replaces the active platform primary seed with a new one generated off the TPM2 RNG. # SYNOPSIS **tpm2_changepps** [*OPTIONS*] # DESCRIPTION **tpm2_changepps**(1) - Replaces the active platform primary seed with a new one generated off the TPM2 RNG. The Transient and Persistent objects under the platform hierarchy are lost whilst retaining the NV objects. # OPTIONS * **-p**, **\--auth** specifies the _AUTH_ for the platform. hierarchy. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. ## References [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Change the platform primary seed where the platform auth is NULL. ```bash tpm2_changepps ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_checkquote.1.md000066400000000000000000000052641412464516500177500ustar00rootroot00000000000000% tpm2_checkquote(1) tpm2-tools | General Commands Manual # NAME **tpm2_checkquote**(1) - Validates a quote provided by a TPM. # SYNOPSIS **tpm2_checkquote** [*OPTIONS*] # DESCRIPTION **tpm2_checkquote**(1) - Uses the public portion of the provided key to validate a quote generated by a TPM. This will validate the signature against the quote message and, if provided, verify that the qualifying data and PCR values match those in the quote. The PCR values can be provided with or without the TPML_PCR_SELECTION information. An example of PCR values without the PCR selection information is the output from **tpm2_pcrread**. If PCR value is specified without the PCR selection information, then the PCR selection string must be specified using the **-l** option to interpret the PCR data. # OPTIONS * **-u**, **\--public**=_FILE_: File input for the public portion of the signature verification key. Either the *pem* file or *tss* public format file. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the message. * **-m**, **\--message**=_FILE_: The quote message that makes up the data that is signed by the TPM. * **-s**, **\--signature**=_FILE_: The input signature file of the signature to be validated. * **-f**, **\--pcr**=_FILE_: Optional PCR input file to save the list of PCR values that were included in the quote. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank. * **-q**, **\--qualification**=_HEX\_STRING\_OR\_PATH_: Qualification data for the quote. Can either be a hex string or path. This is typically used to add a nonce against replay attacks. * **-F**, **\--format**=_FORMAT_: **DEPRECATED** and **IGNORED ** as it's superfluous. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Generate a quote with a TPM, then verify it ```bash tpm2_createek -c 0x81010001 -G rsa -u ekpub.pem -f pem tpm2_createak -C 0x81010001 -c ak.ctx -G rsa -s rsassa -g sha256 \ -u akpub.pem -f pem -n ak.name tpm2_quote -c ak.ctx -l sha256:15,16,22 -q abc123 -m quote.msg -s quote.sig \ -o quote.pcrs -g sha256 tpm2_checkquote -u akpub.pem -m quote.msg -s quote.sig -f quote.pcrs -g sha256 \ -q abc123 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_clear.1.md000066400000000000000000000033541412464516500167010ustar00rootroot00000000000000% tpm2_clear(1) tpm2-tools | General Commands Manual # NAME **tpm2_clear**(1) - Clears lockout, endorsement and owner hierarchy authorization values. # SYNOPSIS **tpm2_clear** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_clear**(1) - Send a clear command to the TPM to clear the 3 hierarchy authorization values. As an argument takes the auth value for either platform or lockout hierarchy **NOTE**: All objects created under the respective hierarchies are lost. # OPTIONS * **-c**, **\--auth-hierarchy**=_OBJECT_: Specifies the hierarchy the tools should operate on. By default it operates on the lockout hierarchy. **NOTE : Operating on platform hierarchy require platform authentication.** * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the _AUTH_ to be set for the object specified with **-c**. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set owner, endorsement and lockout authorizations to an empty value ```bash tpm2_clear lockoutpasswd ``` ## Clear the authorization values on the platform hierarchy ```bash tpm2_clear -c p ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_clearcontrol.1.md000066400000000000000000000044341412464516500203020ustar00rootroot00000000000000% tpm2_clearcontrol(1) tpm2-tools | General Commands Manual # NAME **tpm2_clearcontrol**(1) - Set/ Clear TPMA_PERMANENT.disableClear attribute to effectively block/ unblock lockout authorization handle for issuing TPM clear. # SYNOPSIS **tpm2_clearcontrol** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_clearcontrol**(1) - Allows user with knowledge of either lockout auth and or platform hierarchy auth to set disableClear which prevents the lockout authorization's capability to execute tpm2_clear. Only user with authorization knowledge of the platform hierarchy can clear the disableClear. By default it attempts to clear the disableClear bit. Note: Platform hierarchy auth handle can always be used to clear the TPM with tpm2_clear command. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies what auth handle, either platform hierarchy or lockout the tool should operate on. By default it operates on the platform hierarchy handle. Specify the handle as p|l|platform|lockout. **NOTE : Operating on platform hierarchy require platform authentication.** * **-P**, **\--auth**=_AUTH_: The authorization value of the hierarchy specified with **-C**. This tool only respects the *Password* and *HMAC* options. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** ** Specify an integer 0|1 or string c|s to clear or set the disableClear attribute. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set the disableClear to block the lockout authorization's access to TPM clear ```bash tpm2_clearcontrol -C l s ``` ## Clear the disableClear to unblock lockout authorization for TPM clear ```bash tpm2_clearcontrol -C p c ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_clockrateadjust.1.md000066400000000000000000000044731412464516500210000ustar00rootroot00000000000000% tpm2_clockrateadjust(1) tpm2-tools | General Commands Manual # NAME **tpm2_clockrateadjust**(1) - Sets the clock rate period on the TPM. # SYNOPSIS **tpm2_clockrateadjust** [*OPTIONS*] __ADJUSTER__ # DESCRIPTION **tpm2_clockrateadjust**(1) - Adjusts the rate at which clock and time are updated on the TPM so one can better match real time. With no argument, the command is invoked but the clock rate is not altered. With an argument, the tool will adjust the clock and time period. The command can either increase or decrease the clock period via 3 distinct granularities: course, medium and fine. To specify this, the argument can be a string of 1 to 3 characters of *all* 's' or 'f'. ## Valid Adjuster Arguments * s - slows down the clock period one fine increment. * ss - slows down the clock period one medium increment. * sss - slows down the clock period one course increment. * f - speeds up the clock period one fine increment. * ff - speeds up the clock period one medium increment. * fff - speeds up the clock period one course increment. # OPTIONS * **-c**, **\--hierarchy**=_OBJECT_: The hierarchy to use for authorization, either platform or owner. Defaults to the owner hierarchy if not specified. * **-p**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy specified by option **-c**. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set the clock Slow the clock one medium increment using the owner password. ```bash tpm2_clockrateadjust -p ownerpw ss ``` Speed up the clock one course increment using the platform password. ```bash tpm2_clockrateadjust -c p -p platformpw fff ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_commit.1.md000066400000000000000000000040251412464516500170770ustar00rootroot00000000000000% tpm2_commit(1) tpm2-tools | General Commands Manual # NAME **tpm2_commit**(1) - Performs the first part of an ECC anonymous signing operation. # SYNOPSIS **tpm2_commit** [*OPTIONS*] # DESCRIPTION **tpm2_commit**(1) - Performs the first part of an ECC anonymous signing operation. The TPM will perform the point multiplications on the provided points and return intermediate signing values. The signing key is an ECC key. The key cannot be a sign+decrypt key and must have an anonymous signing scheme. TPM_ALG_ECDAA is the only supported anonymous scheme. # OPTIONS * **ARGUMENT**=_FILE_: Specify the input data used to derive the x coordinate of the basepoint. * **\--basepoint-y**=_FILE_: Specify the y coordinate of the basepoint. * **\--eccpoint-P**=_FILE_: Specify a point on the curve used by sign handle. * **\--eccpoint-K**=_FILE_: Output ECC point K ≔ \[ds\](x2, y2). * **\--eccpoint-L**=_FILE_: Output ECC point L ≔ \[r\](x2, y2). * **-u**, **\--public**=_FILE_: Output ECC point E ≔ [r]P1. * **-t**, **\--counter**=_FILE_ Specify file path to save the least-significant 16 bits of commit count. * **-p**, **\--auth**=_AUTH_: The authorization value for the created object. * **-c**, **\--context**=_FILE_: Context object pointing to the the key used for signing. Either a file or a handle number. See section "Context Object Format". ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -C o -c prim.ctx -Q tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv -G ecc256:ecdaa tpm2_commit -c key.ctx -t count.er \ --eccpoint-K K.bin --eccpoint-L L.bin -u E.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_create.1.md000066400000000000000000000162621412464516500170600ustar00rootroot00000000000000% tpm2_create(1) tpm2-tools | General Commands Manual # NAME **tpm2_create**(1) - Create a child object. # SYNOPSIS **tpm2_create** [*OPTIONS*] # DESCRIPTION **tpm2_create**(1) - Create a child object. The object can either be a key or a sealing object. A sealing object allows to seal user data to the TPM, with a maximum size of 128 bytes. Additionally it will load the created object if the **-c** is specified. # OPTIONS These options for creating the TPM entity: * **-C**, **\--parent-context**=_OBJECT_: The parent of the object to be created. * **-P**, **\--parent-auth**=_AUTH_: The authorization value of the parent object specified with **-C**. * **-p**, **\--key-auth**=_AUTH_: The authorization value for the created object. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm for generating the objects name. This is optional and defaults to sha256 when not specified. * **-G**, **\--key-algorithm**=_ALGORITHM_: The key algorithm associated with this object. It defaults to "rsa" if not specified. * **-a**, **\--attributes**=_ATTRIBUTES_: The object attributes, optional. The default for created objects is: `TPMA_OBJECT_SIGN_ENCRYPT|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM| TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN| TPMA_OBJECT_USERWITHAUTH` When **-i** is specified for sealing, `TPMA_OBJECT_SIGN_ENCRYPT` and `TPMA_OBJECT_DECRYPT` are removed from the default attribute set. The algorithm is set in a way where the the object is only good for sealing and unsealing. I.e. one cannot use an object for sealing and cryptography operations. When **-L** is specified for adding policy based authorization information AND no string password is specified, the attribute `TPMA_OBJECT_USERWITHAUTH` is cleared unless an explicit choice is made by setting of the attribute with **-a** option. This prevents creation of objects with inadvertant auth model where in user intended to enforce a policy but inadvertantly created an object with empty auth which can be used instead of policy authorization. * **-i**, **\--sealing-input**=_FILE_ or _STDIN_: The data file to be sealed, optional. If file is -, read from stdin. When sealing data only the _TPM\_ALG\_KEYEDHASH_ algorithm with a NULL scheme is allowed. Thus, **-G** cannot be specified. * **-L**, **\--policy**=_FILE_: The input policy file, optional. * **-u**, **\--public**=_FILE_: The output file which contains the public portion of the created object, optional. * **-r**, **\--private**=_FILE_: The output file which contains the sensitive portion of the object, optional. [protection details](common/protection-details.md) * **-c**, **\--key-context**=_FILE_: The output file which contains the key context, optional. The key context is analogous to the context file produced by **tpm2_load**(1), however is generated via a **tpm2_createloaded**(1) command. This option can be used to avoid the normal **tpm2_create**(1) and **tpm2_load**(1) command sequences and do it all in one command, atomically. * **\--creation-data**=_FILE_: An optional file output that saves the creation data for certification. * **\--template-data**=_FILE_: An optional file output that saves the key template data (TPM2B_PUBLIC) to be used in **tpm2_policytemplate**. * **-t**, **\--creation-ticket**=_FILE_: An optional file output that saves the creation ticket for certification. * **-d**, **\--creation-hash**=_FILE_: An optional file output that saves the creation hash for certification. * **-q**, **\--outside-info**=_HEX\_STR\_OR\_FILE_: An optional hex string or path to add unique data to the creation data. Note that it does not contribute in creating statistically unique object. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank to be included in the creation data for certification. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption/decryption of the parameters. [pubkey options](common/pubkey.md) Public key format. * **-o**, **\--output**=_FILE_: The output file path, recording the public portion of the object. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [object attribute specifiers](common/obj-attrs.md) details the options for specifying the object attributes _ATTRIBUTES_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Setup In order to create an object, we must first create a primary key as it's parent. ```bash tpm2_createprimary -c primary.ctx ``` ## Create an Object This will create an object using all the default values and store the TPM sealed private and public portions to the paths specified via -u and -r respectively. The tool defaults to an RSA key. ```bash tpm2_create -C primary.ctx -u obj.pub -r obj.priv ``` ## Seal Data to the TPM Outside of key objects, the TPM allows for small amounts of user specified data to be sealed to the TPM. ```bash echo "my sealed data" > seal.dat tpm2_create -C primary.ctx -i seal.dat -u obj.pub -r obj.priv ``` ## Create an EC Key Object and Load it to the TPM Normally, when creating an object, only the public and private portions of the object are returned and the caller needs to use tpm2\_load(1) to load those public and private portions to the TPM before being able to use the object. However, this can be accomplished within this command as well, when supported by the TPM. You can verify your TPM supports this feature by checking that tpm2\_getcap(1) commands returns TPM2\_CC\_CreateLoaded in the command set. If your TPM does not support TPM2\_CC\_CreateLoaded an unsuported command code error will be returned. If it's not supported one must use tpm2\_load(1). See that manpage for details on its usage. ```bash tpm2_create -C primary.ctx -G ecc -u obj.pub -r obj.priv -c ecc.ctx ``` ## Create an Object and get the public key as a PEM file This will create an object using all the default values but also output the public key as a PEM file compatible with tools like OpenSSL and whatever supports PEM files. ```bash tpm2_create -C primary.ctx -u obj.pub -r obj.priv -f pem -o obj.pem ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_createak.1.md000066400000000000000000000057171412464516500173770ustar00rootroot00000000000000% tpm2_createak(1) tpm2-tools | General Commands Manual # NAME **tpm2_createak**(1) - Generate attestation key with given algorithm under the endorsement hierarchy. # SYNOPSIS **tpm2_createak** [*OPTIONS*] # DESCRIPTION **tpm2_createak**(1) - Generate an attestation key (AK) with the given algorithm under the endorsement hierarchy. The context of the attestation key is specified via **-c**. The tool outputs to stdout a YAML representation of the loaded key's name, for example: ``` loaded-key: name: 000bac149518baa05540a0678bd9b624f8a98d042e46c60f4d098ba394d36fc49268 ``` # OPTIONS * **-P**, **\--eh-auth**=_AUTH_: The authorization value for the endorsement hierarchy. * **-p**, **\--ak-auth**=_AUTH_ The authorization value for the attestation key object created. * **-C**, **\--ek-context**=_OBJECT_: The endorsement key object. * **-c**, **\--ak-context**=_FILE_: The file path to save the object context of the attestation key. * **-G**, **\--key-algorithm**=_ALGORITHM_: Specifies the attestation key algorithm. Supports: * ecc - An P256 key. * rsa - An RSA2048 key. * keyedhash - hmac key. * **-g**, **\--hash-algorithm**=_ALGORITHM_: Specifies the digest algorithm used for signing. * **-s**, **\--signing-algorithm**=_ALGORITHM_: The signing algorithm. * **-u**, **\--public**=_FILE_: The file to save the public portion of the attestation key. * **-n**, **\--ak-name**=_FILE_: The file to save the attestation key name, optional. * **-r**, **\--private**=_FILE_: The output file which contains the sensitive portion of the object, optional. [protection details](common/protection-details.md) [pubkey options](common/pubkey.md) Format selection for the signature output file. * **-q**, **\--ak-qualified-name**=_FILE_: The qualified name of the attestation key object. The qualified name is the qualified name of the parent object (the EK in this instance) and the name of the object itself. Thus, the qualified name of an object serves to bind it to its parents. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ### Create an Attestation Key and make it persistent ```bash tpm2_createek -c ek.handle -G rsa -u ek.pub tpm2_createak -C ek.handle -c ak.ctx -u ak.pub -n ak.name tpm2_evictcontrol -C o -c ak.ctx 0x81010002 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_createek.1.md000066400000000000000000000060401412464516500173710ustar00rootroot00000000000000% tpm2_createek(1) tpm2-tools | General Commands Manual # NAME **tpm2_createek**(1) - Generate TCG profile compliant endorsement key. # SYNOPSIS **tpm2_createek** [*OPTIONS*] # DESCRIPTION **tpm2_createek**(1) - Generate TCG profile compliant endorsement key (EK), which is the primary object of the endorsement hierarchy. If a transient object is generated the tool outputs a context file specified with **-c**. Refer to: # OPTIONS * **-P**, **\--eh-auth**=_AUTH_: The authorization value for the endorsement hierarchy * **-w**, **\--owner-auth**=_AUTH_ The authorization value for the owner hierarchy. * **-c**, **\--ek-context**=_OBJECT_ or _FILE_: Either a file path or a persistent handle value to save the endorsement key. If a value of **-** is passed the tool will find a vacant persistent handle to use and print out the automatically selected handle. If one saves the context file via this option and the public key via the **-u** option, the EK can be restored via a call to **tpm2_loadexternal**(1). * **-G**, **\--key-algorithm**=_ALGORITHM_: The endorsement key algorithm. Supports: * **ecc** - An P256 key. * **rsa** - An RSA2048 key. * **keyedhash** - hmac key. * **-u**, **\--public**=_FILE_: The optional input for a file to save the public portion of endorsement key. * **-t**, **\--template**: The optional manufacturer defined endorsement key template and nonce from fixed NV Indices to populate the **TPM2B_PUBLIC** public area. See the TCG EK Credential Profile specification for more information: https://trustedcomputinggroup.org/wp-content/uploads/ TCG_IWG_Credential_Profile_EK_V2.1_R13.pdf [pubkey options](common/pubkey.md) Public key format. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ### Create an Endorsement Key and make it persistent ```bash tpm2_createek -P abc123 -w abc123 -c 0x81010001 -G rsa -u ek.pub ``` ### Create a transient Endorsement Key, flush it, and reload it. ```bash tpm2_createek -G rsa -u ek.pub # Check that it is loaded in transient memory tpm2_getcap handles-transient - 0x80000000 # Flush the handle tpm2_flushcontext 0x80000000 # Note that it is flushed tpm2_getcap handles-transient # Reload it via loadexternal tpm2_loadexternal -C o -u ek.pub -c ek.ctx # Check that it is re-loaded in transient memory tpm2_getcap handles-transient - 0x80000000 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_createpolicy.1.md000066400000000000000000000036301412464516500202730ustar00rootroot00000000000000% tpm2_createpolicy(1) tpm2-tools | General Commands Manual # NAME **tpm2_createpolicy**(1) - Creates simple assertion authorization policies based on multiple PCR indices values across multiple enabled banks. # SYNOPSIS **tpm2_createpolicy** [*OPTIONS*] # DESCRIPTION **tpm2_createpolicy**(1) - Creates simple assertion authorization policies based on multiple PCR indices values across multiple enabled banks. It can then be used with object creation and or tools using the object. # OPTIONS These options control creating the policy authorization session: * **-L**, **\--policy**=_FILE_: The file to save the policy digest. * **\--policy-pcr**: Identifies the PCR policy type for policy creation. * **-g**, **\--policy-algorithm**=_ALGORITHM_: The hash algorithm used in computation of the policy digest. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank. * **-f**, **\--pcr**=_FILE_: Optional Path or Name of the file containing expected PCR values for the specified index. Default is to read the current PCRs per the set list. * **\--policy-session**: Start a policy session of type **TPM_SE_POLICY**. Defaults to **TPM_SE_TRIAL** if this option isn't specified. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/pcr.md) details options for specifying the pcr index and bank/algorithm _PCR_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create a authorization policy tied to a specific PCR index ```bash tpm2_createpolicy \--policy-pcr -l 0x4:0 -L policy.file -f pcr0.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_createprimary.1.md000066400000000000000000000137251412464516500204650ustar00rootroot00000000000000% tpm2_createprimary(1) tpm2-tools | General Commands Manual # NAME **tpm2_createprimary**(1) - Create a primary key. # SYNOPSIS **tpm2_createprimary** [*OPTIONS*] # DESCRIPTION **tpm2_createprimary**(1) - This command is used to create a primary object under one of the hierarchies: Owner, Platform, Endorsement, NULL. The command will create and load a Primary Object. The sensitive and public portions are not returned. A context file for the created object's handle is saved as a file for future interactions with the created primary. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: The hierarchy under which the object is created. This will also dictate which authorization secret (if any) must be supplied. Defaults to **TPM_RH_OWNER**, when no value specified. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **e** for **TPM_RH_ENDORSEMENT** * **n** for **TPM_RH_NULL** * **``** where a raw number can be used. * **-P**, **\--hierarchy-auth**=_AUTH_: The authorization value for the hierarchy specified with **-C**. * **-p**, **\--key-auth**=_AUTH_: The authorization value for the primary object created. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm to use for generating the objects name. Defaults to sha256 if not specified. * **-G**, **\--key-algorithm**=_ALGORITHM_: The algorithm type for the generated primary key. Defaults to rsa2048:null:aes128cfb. * **-c**, **\--key-context**=_FILE_: The file path to save the object context of the generated primary object. * **-L**, **\--policy**=_FILE_: An optional file input that contains the policy digest for policy based authorization of the object. * **-a**, **\--attributes**=_ATTRIBUTES_: The object attributes, optional. Defaults to: `TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_FIXEDTPM| TPMA_OBJECT_FIXEDPARENT|TPMA_OBJECT_SENSITIVEDATAORIGIN| TPMA_OBJECT_USERWITHAUTH` * **-u**, **\--unique-data**=_FILE_ OR _STDIN_: An optional file input that contains the unique field of **TPMT_PUBLIC** in little-endian format. Primary key creator may place information that causes the primary key generation scheme internal to the TPM to generate statistically unique values. The TPM v2.0 specification calls this field unique and overloads it so that it contains one value when the application provides this structure as input and another value when the applications receives this structure as output (like public portion of the rsa key). If the data is specified as a file, the user is responsible for ensuring that this buffer is formatted per TPMU_PUBLIC_ID union. The unique data can also be retrieved from stdin buffer by specifying **"-"** as the **--unique-data** option value and the tool will parse the key type and associate the input data with the unique data buffer associated with the key type. NOTE: 1. The maximum allowed bytes is dependent on key type and the TPM implementation. Eg. While TSS allows a value upto 512 for MAX_RSA_KEY_BYTES, however the ibmSwTPM implementation supports a value upto 256 bytes. 2. The unique input data specified on stdin for ECC is split for specifying the X coordinate and Y coordinate buffers. * **\--creation-data**=_FILE_: An optional file output that saves the creation data for certification. * **\--template-data**=_FILE_: An optional file output that saves the key template data (TPM2B_PUBLIC) to be used in **tpm2_policytemplate**. * **-t**, **\--creation-ticket**=_FILE_: An optional file output that saves the creation ticket for certification. * **-d**, **\--creation-hash**=_FILE_: An optional file output that saves the creation hash for certification. * **-q**, **\--outside-info**=_FILE\_OR\_HEX_: An optional file or hex string to add unique data to the creation data. Note that it does not contribute in creating statistically unique object. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank to be included in the creation data for certification. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. [pubkey options](common/pubkey.md) Public key format. * **-o**, **\--output**=_FILE_: The output file path, recording the public portion of the object. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [object attribute specifiers](common/obj-attrs.md) details the options for specifying the object attributes _ATTRIBUTES_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create an ECC primary object ```bash tpm2_createprimary -C o -g sha256 -G ecc -c context.out ``` ## Create a primary object that follows the guidance of TCG Provisioning guide See : https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf Where unique.dat contains the binary-formatted data: 0x00 0x01 (0x00 * 256) ```bash tpm2_createprimary -C o -G rsa2048:aes128cfb -g sha256 -c prim.ctx \ -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|\ noda' -u unique.dat ## Create a primary object and output the public key in pem format ```bash tpm2_createprimary -c primary.ctx --format=pem --output=public.pem ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_dictionarylockout.1.md000066400000000000000000000037621412464516500213640ustar00rootroot00000000000000% tpm2_dictionarylockout(1) tpm2-tools | General Commands Manual # NAME **tpm2_dictionarylockout**(1) - Setup or clear dictionary-attack-lockout parameters. # SYNOPSIS **tpm2_dictionarylockout** [*OPTIONS*] # DESCRIPTION **tpm2_dictionarylockout**(1) - Setup dictionary-attack-lockout parameters or clear dictionary-attack-lockout state. # OPTIONS * **-s**, **\--setup-parameters**: Specifies the tool should operate to setup dictionary-attack-lockout parameters. * **-c**, **\--clear-lockout**: Specifies the tool should operate to clear dictionary-attack-lockout state. * **-l**, **\--lockout-recovery-time**=_NATURAL_NUMBER_: Specifies the wait time in seconds before another **TPM_RH_LOCKOUT** authentication attempt can be made after a failed authentication. * **-t**, **\--recovery-time**=_NATURAL_NUMBER_: Specifies the wait time in seconds before another DA-protected-object authentication attempt can be made after max-tries number of failed authentications. * **-n**, **\--max-tries**=_NATURAL_NUMBER_: Specifies the maximum number of allowed authentication attempts on DA-protected-object; after which DA is activated. * **-p**, **\--auth**=_AUTH_: The authorization value for the lockout handle. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_dictionarylockout -c -p passwd tpm2_dictionarylockout -s -n 5 -t 6 -l 7 -p passwd ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_duplicate.1.md000066400000000000000000000200621412464516500175600ustar00rootroot00000000000000% tpm2_duplicate(1) tpm2-tools | General Commands Manual # NAME tpm2_duplicate(1) - Duplicates a loaded object so that it may be used in a different hierarchy. # SYNOPSIS **tpm2_duplicate** [*OPTIONS*] # DESCRIPTION **tpm2_duplicate**(1) - This tool duplicates a loaded object so that it may be used in a different hierarchy. The new parent key for the duplicate may be on the same or different TPM or TPM_RH_NULL. # OPTIONS These options control the key importation process: * **-G**, **\--wrapper-algorithm**=_ALGORITHM_: The symmetric algorithm to be used for the inner wrapper. Supports: * aes - AES 128 in CFB mode. * null - none * **-i**, **\--encryptionkey-in**=_FILE_: Specifies the filename of the symmetric key (128 bit data) to be used for the inner wrapper. Valid only when specified symmetric algorithm is not null * **-o**, **\--encryptionkey-out**=_FILE_: Specifies the filename to store the symmetric key (128 bit data) that was used for the inner wrapper. Valid only when specified symmetric algorithm is not null and \--input-key-file is not specified. The TPM generates the key in this case. * **-C**, **\--parent-context**=_OBJECT_: The parent key object. * **-U**, **\--parent-public**=_FILE_: Specifies the file path to the public key of the parent object on the destination TPM. This should be a `TPM2B_PUBLIC` formatted file. * **-k**, **\--private-key**=_FILE_: Specifies the file path to the external private key be encrypted for the remote TPM. This should be a PEM format private key. * **-r**, **\--private**=_FILE_: Specifies the file path to save the private portion of the duplicated object. [protection details](common/protection-details.md) * **-u**, **\--public**=_FILE_: Specifies the file path to save the public portion of the duplicated object, if an external key is being duplicated. * **-s**, **\--encrypted-seed**=_FILE_: The file to save the encrypted seed of the duplicated object. * **-p**, **\--auth**=_AUTH_: The authorization value for the key, optional. * **-L**, **\--policy**=_FILE_: The input policy file, optional. * **-c**, **\--key-context**=_OBJECT_: The object to be duplicated. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES To duplicate a key, one needs the key to duplicate, created with a policy that \ allows duplication and a new parent: ```bash tpm2_startauthsession -S session.dat tpm2_policycommandcode -S session.dat -L policy.dat TPM2_CC_Duplicate tpm2_flushcontext session.dat tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctxt tpm2_create -C primary.ctxt -g sha256 -G rsa -r key.prv -u key.pub \ -L policy.dat -a "sensitivedataorigin" tpm2_loadexternal -C o -u new_parent.pub -c new_parent.ctxt tpm2_startauthsession \--policy-session -S session.dat tpm2_policycommandcode -S session.dat -L policy.dat TPM2_CC_Duplicate tpm2_duplicate -C new_parent.ctxt -c key.ctxt -G null -p "session:session.dat" \ -r duprv.bin -s seed.dat tpm2_flushcontext session.dat ``` As an end-to-end example, the following will transfer an RSA key generated on `TPM-A` to `TPM-B` ## On TPM-B Create a parent object that will be used to wrap/transfer the key. ``` tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx tpm2_create -C primary.ctx -g sha256 -G rsa \ -r new_parent.prv -u new_parent.pub \ -a "restricted|sensitivedataorigin|decrypt|userwithauth" ``` Copy `new_parent.pub` to `TPM-A`. ## On TPM-A Create root object and auth policy allows duplication only ``` tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx tpm2_startauthsession -S session.dat tpm2_policycommandcode -S session.dat -L dpolicy.dat TPM2_CC_Duplicate tpm2_flushcontext session.dat rm session.dat ``` Generate an RSA keypair on TPM-A that will be duplicated (note the passphrase is 'foo') ``` tpm2_create -C primary.ctx -g sha256 -G rsa -p foo -r key.prv \ -u key.pub -L dpolicy.dat -a "sensitivedataorigin|userwithauth|decrypt|sign" tpm2_load -C primary.ctx -r key.prv -u key.pub -c key.ctx tpm2_readpublic -c key.ctx -o dup.pub ``` Test sign and encryption locally (so we can compare later that the same key was transferred). ``` echo "meet me at.." >file.txt tpm2_rsaencrypt -c key.ctx -o data.encrypted file.txt tpm2_sign -c key.ctx -g sha256 -f plain -p foo -o sign.raw file.txt ``` Compare the signature hash (we will use this later to confirm the key was transferred to TPM-B): ``` sha256sum sign.raw a1b4e3fbaa29e6e46d95cff498150b6b8e7d9fd21182622e8f5a3ddde257879e ``` Start an auth session and policy command to allow duplication ``` tpm2_startauthsession --policy-session -S session.dat tpm2_policycommandcode -S session.dat -L dpolicy.dat TPM2_CC_Duplicate ``` Load the new_parent.pub file transferred from `TPM-B` ``` tpm2_loadexternal -C o -u new_parent.pub -c new_parent.ctx ``` Start the duplication ``` tpm2_duplicate -C new_parent.ctx -c key.ctx -G null \ -p "session:session.dat" -r dup.dpriv -s dup.seed ``` Copy the following files to TPM-B: * dup.pub * dup.dpriv * dup.seed * (optionally data.encrypted just to test decryption) ## On TPM-B Start an auth,policy session ``` tpm2_startauthsession --policy-session -S session.dat tpm2_policycommandcode -S session.dat -L dpolicy.dat TPM2_CC_Duplicate ``` Load the context we used to transfer ``` tpm2_flushcontext --transient-object tpm2_load -C primary.ctx -u new_parent.pub -r new_parent.prv -c new_parent.ctx ``` Import the duplicated context against the parent we used ``` tpm2_import -C new_parent.ctx -u dup.pub -i dup.dpriv \ -r dup.prv -s dup.seed -L dpolicy.dat ``` Load the duplicated key context ``` tpm2_flushcontext --transient-object tpm2_load -C new_parent.ctx -u dup.pub -r dup.prv -c dup.ctx ``` Test the imported key matches * Sign ```bash echo "meet me at.." >file.txt tpm2_sign -c dup.ctx -g sha256 -o sig.rss -p foo file.txt dd if=sig.rss of=sign.raw bs=1 skip=6 count=256 ``` Compare the signature file hash: ```bash $ sha256sum sign.raw a1b4e3fbaa29e6e46d95cff498150b6b8e7d9fd21182622e8f5a3ddde257879e ``` * Decryption ``` tpm2_flushcontext --transient-object tpm2_rsadecrypt -p foo -c dup.ctx -o data.ptext data.encrypted # cat data.ptext meet me at.. ``` ## Exporting an OpenSSL RSA key for a remote TPM To securely send an OpenSSL generated RSA key to a remote TPM such that only that remote TPM will be able to load it, and without exposing the private key to the host operating system on the remote machine: * On the destination TPM-B, create a primary context and read its public key, then send `primary.pub` to the source machine: ```bash tpm2_createprimary -c primary.ctx tpm2_readpublic -c primary.ctx -o primary.pub ``` * On the source machine create the RSA private key and wrap it for the destination TPM's public key. Similar to `tpm2_makecredential`, this step should not require a TPM. ```bash openssl genrsa -out rsa.pem tpm2_duplicate -U primary.pub -G rsa -k rsa.pem -u rsa.pub -r rsa.dpriv -s rsa.seed ``` * Send the `rsa.pub`, `rsa.dpriv` and `rsa.seed` to the destination TPM-B and import the files, which will decrypt them using the `primary.ctx` to produce `rsa.priv`, which can then be loaded and used as a TPM key: ```bash tpm2_import -C primary.ctx -G rsa -i rsa.dpriv -s rsa.seed -u rsa.pub -r rsa.priv tpm2_load -C primary.ctx -c rsa.ctx -u rsa.pub -r rsa.priv ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_ecdhkeygen.1.md000066400000000000000000000025041412464516500177150ustar00rootroot00000000000000% tpm2_ecdhkeygen(1) tpm2-tools | General Commands Manual # NAME **tpm2_ecdhkeygen**(1) - Creates an ephemeral key and uses it to generate the shared secret value using the parameters from a ECC public key. # SYNOPSIS **tpm2_ecdhkeygen** [*OPTIONS*] # DESCRIPTION **tpm2_ecdhkeygen**(1) - Creates an ephemeral key and uses it to generate the shared secret value using the parameters from a ECC public key. # OPTIONS * **-c**, **\--context**=_FILE_: Context object pointing to ECC public key. Either a file or a handle number. See section "Context Object Format". * **-u**, **\--public**=_FILE_: Output ECC point Q. * **-o**, **\--output**=_FILE_ Specify file path to save the calculated ecdh secret or Z point. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -C o -c prim.ctx -Q tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv -G ecc256:ecdaa tpm2_ecdhkeygen -u ecdh.pub -o ecdh.priv -c key.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_ecdhzgen.1.md000066400000000000000000000031251412464516500173760ustar00rootroot00000000000000% tpm2_ecdhzgen(1) tpm2-tools | General Commands Manual # NAME **tpm2_ecdhzgen**(1) - Recovers the shared secret value (Z) from a public point and a specified private key. # SYNOPSIS **tpm2_ecdhzgen** [*OPTIONS*] # DESCRIPTION **tpm2_ecdhzgen**(1) - Recovers the shared secret value (Z) from a public point and a specified private key. It will perform the multiplication of the provided inPoint (QB) with the private key (ds) and return the coordinates of the resultant point (Z = (xZ , yZ) ≔ [hds]QB; where h is the cofactor of the curve). # OPTIONS * **-c**, **\--key-context**=_FILE_: Context object pointing to ECC key. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--key-auth**=_AUTH_: The authorization value for the ECC key object. * **-u**, **\--public**=_FILE_: Output ECC point Q. * **-o**, **\--output**=_FILE_ Specify file path to save the calculated ecdh secret or Z point. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -C o -c prim.ctx -Q tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv -G ecc256:ecdh tpm2_ecdhkeygen -u ecdh.pub -o ecdh.priv -c key.ctx tpm2_ecdhzgen -u ecdh.pub -o ecdh.dat -c key.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_ecephemeral.1.md000066400000000000000000000021261412464516500200610ustar00rootroot00000000000000% tpm2_ecephemeral(1) tpm2-tools | General Commands Manual # NAME **tpm2_ecephemeral**(1) - Creates an ephemeral key for use in a two-phase key exchange protocol. # SYNOPSIS **tpm2_ecephemeral** [*OPTIONS*] # DESCRIPTION **tpm2_ecephemeral**(1) - Creates an ephemeral key for use in a two-phase key exchange protocol. # OPTIONS * **ARGUMENT**=_ALGORITHM_: Specify the ECC curve. Example ecc521. * **-u**, **\--public**=_FILE_ Specify the file path to save the ephemeral public point Q ≔ [r]G. * **-t**, **\--counter**=_FILE_ Specify file path to save the least-significant 16 bits of commit count. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_ecephemeral -u ecc.q -t ecc.ctr ecc256 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_encryptdecrypt.1.md000066400000000000000000000055551412464516500206770ustar00rootroot00000000000000% tpm2_encryptdecrypt(1) tpm2-tools | General Commands Manual # NAME **tpm2_encryptdecrypt**(1) - Performs symmetric encryption or decryption. # SYNOPSIS **tpm2_encryptdecrypt** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_encryptdecrypt**(1) - Performs symmetric encryption or decryption with a specified symmetric key on the contents of _FILE_. If _FILE_ is not specified, defaults to *stdin*. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: The encryption key object. * **-p**, **\--auth**=_AUTH_: The authorization value for the encryption key object. * **-d**, **\--decrypt**: Perform a decrypt operation. Defaults to encryption when this option is not specified. * **-e**, **\--pad**: Enable pkcs7 padding for applicable AES encryption modes cfb/cbc/ecb. Applicable only to encryption and for input data with last block shorter than encryption block length. * **-o**, **\--output**=_FILE_ or _STDOUT_: The output file path for either the encrypted or decrypted data. If not specified, defaults to **stdout**. * **-G**, **\--mode**=_ALGORITHM_: The key algorithm associated with this object. Defaults to object properties or CFB if not defined. * **-t**, **\--iv**=_FILE_: Optional initialization vector to use. Defaults to 0's. Syntax allows for an input file and output file source to be specified. The input file path is first, optionally followed by a colon ":" and the output iv path. This output iv can be saved for subsequent calls when chaining. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the input file path _FILE_ of the data to encrypt or decrypt. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES # Create an AES key ```bash tpm2_createprimary -c primary.ctx tpm2_create -C primary.ctx -Gaes128 -u key.pub -r key.priv tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx ``` # Encrypt and Decrypt some data ```bash echo "my secret" > secret.dat tpm2_encryptdecrypt -c key.ctx -o secret.enc secret.dat tpm2_encryptdecrypt -d -c key.ctx -o secret.dec secret.enc cat secret.dec my secret ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_eventlog.1.md000066400000000000000000000015561412464516500174400ustar00rootroot00000000000000% tpm2_eventlog(1) tpm2-tools | General Commands Manual # NAME **tpm2_eventlog**(1) - Display tpm2 event log. # SYNOPSIS **tpm2_eventlog** [*ARGUMENT*] # DESCRIPTION **tpm2_eventlog**(1) - Parse a binary TPM2 event log. The event log may be passed to the tool as the final positional parameter. If this parameter is omitted the tool will return an error. The format of this log documented in the "TCG PC Client Platform Firmware Profile Specification". # OPTIONS This tool takes no tool specific options. * **ARGUMENT** The command line argument is the path to a binary TPM2 eventlog. ## References [common options](common/options.md) collection of common options that provide information many users may expect. # EXAMPLES ```bash # display eventlog from provided file tpm2_eventlog eventlog.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_evictcontrol.1.md000066400000000000000000000071161412464516500203260ustar00rootroot00000000000000% tpm2_evictcontrol(1) tpm2-tools | General Commands Manual # NAME **tpm2_evictcontrol**(1) - Make a transient object persistent or evict a persistent object. # SYNOPSIS **tpm2_evictcontrol** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_evictcontrol**(1) - Allows a transient object to be made persistent or a persistent object to be evicted. The _HANDLE_ argument controls the index the handle will be assigned to. If the object specified via **-c** is transient, and a permanent _HANDLE_ is specified, the object will be persisted at _HANDLE_. If _HANDLE_ is a -, then the object will be persisted at the first available permanent handle location. If the object specified via **-c** is a permanent handle, then the object will be evicted from it's permenent handle location. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: The authorization hierarchy used to authorize the commands. Defaults to the "owner" hierarchy. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a raw number can be used. * **-c**, **\--object-context**=_OBJECT_: A context object specifier of a transient or persistent object. If _OBJECT_ is a transient object it will be persisted, either to the handle specified by the argument or to first available vacant persistent handle. If the _OBJECT_ is for a persistent object, then the object will be evicted from non-volatile memory. * **-P**, **\--auth**=_AUTH_: The authorization value for the hierarchy specified with **-C**. * **-o**, **\--output**=_FILE_: Optionally output a serialized object representing the persistent handle. If untampered, these files are safer to use then raw persistent handles. A raw persistent handle should be verified that the object it points to is as expected. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the persistent handle to save the transient object to. # Output The tool outputs a YAML compliant dictionary with the fields: persistent-handle: action: evicted|persisted Where *persistent-handle* is the handle the action occurred to. Where *action* can either be one of *evicted* or *persisted*. If an object is *evicted* then the object is no longer resident at the *persistent-handle* address within the TPM. If an object is *persisted* then the object is resident at the *persistent-handle* address within the TPM. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## To make a transient handle persistent at address 0x81010002 ```bash tpm2_changeauth -c o ownerauth tpm2_createprimary -c primary.ctx -P ownerauth tpm2_evictcontrol -C o -c primary.ctx 0x81010002 -P ownerauth ``` ## To evict a persistent handle ```bash tpm2_evictcontrol -C o -c 0x81010002 -P ownerauth ``` ## To make a transient handle persistent and output a serialized persistent handle. ```bash tpm2_evictcontrol -C o -c primary.ctx -o primary.handle -P ownerauth ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_flushcontext.1.md000066400000000000000000000040061412464516500203340ustar00rootroot00000000000000% tpm2_flushcontext(1) tpm2-tools | General Commands Manual # NAME **tpm2_flushcontext**(1) - Remove a specified handle, or all contexts associated with a transient object, loaded session or saved session from the TPM. # SYNOPSIS **tpm2_flushcontext** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_flushcontext**(1) - Remove a specified handle, or all contexts associated with a transient object, loaded session or saved session from the TPM. The object to be flushed is specified as the first argument to the tool and is in one of the following forms: - The handle of the object to be flushed from the TPM. Must be a valid handle number. - Flush a session via a session file. A session file is generated from **tpm2_startauthsession**(1)'s **-S** option. # OPTIONS * **-t**, **\--transient-object**: Remove all transient objects. * **-l**, **\--loaded-session**: Remove all loaded sessions. * **-s**, **\--saved-session**: Remove all saved sessions. * **ARGUMENT** the command line argument specifies the _OBJECT_ to be removed from the TPM resident memory. [common options](common/options.md) [common tcti options](common/tcti.md) # EXAMPLES ## Flushing a Transient Object Typically, when using the TPM, the interactions occur through a resource manager, like tpm2-abrmd(8). When the process exits, transient object handles are flushed. Thus, flushing transient objects through the command line is not required. However, when interacting with the TPM directly, this scenario is possible. The below example assumes direct TPM access not brokered by a resource manager. Specifically we will use the simulator. ```bash tpm2_createprimary -Tmssim -c primary.ctx tpm2_getcap -T mssim handles-transient - 0x80000000 tpm2_flushcontext -T mssim 0x80000000 ``` ## Flush All the Transient Objects ```bash tpm2_flushcontext \--transient-object ``` ## Flush a Session ```bash tpm2_startauthsession -S session.dat tpm2_flushcontext session.dat ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getcap.1.md000066400000000000000000000035121412464516500170520ustar00rootroot00000000000000% tpm2_getcap(1) tpm2-tools | General Commands Manual # NAME **tpm2_getcap**(1) - Display TPM capabilities in a human readable form. # SYNOPSIS **tpm2_getcap** [*OPTIONS*] [*CAPABILITY*] # DESCRIPTION **tpm2_getcap**(1) - Query the TPM for it's capabilities / properties and print them to the console. It takes a string form of the capability to query as an argument to the tool. Currently supported capability groups are: - **algorithms**: Display data about supported algorithms. - **commands**: Display data about supported commands. - **pcrs**: Display currently allocated PCRs. - **properties-fixed**: Display fixed TPM properties. - **properties-variable**: Display variable TPM properties. - **ecc-curves**: Display data about elliptic curves. - **handles-transient**: Display handles about transient objects. - **handles-persistent**: Display handles about persistent objects. - **handles-permanent**: Display handles about permanent objects. - **handles-pcr**: Display handles about PCRs. - **handles-nv-index**: Display handles about NV Indices. - **handles-loaded-session**: Display handles about both loaded HMAC and policy sessions. - **handles-saved-session**: Display handles about saved sessions. # OPTIONS * **-l**, **\--list**: List known supported capability names. These names can be supplied as the argument to the **-c** option. Output is in a YAML compliant list to stdout. For example: ``` - algorithms - commands - properties-fixed ... ``` [common options](common/options.md) [common tcti options](common/tcti.md) # EXAMPLES ## To list the fixed properties of the TPM ```bash tpm2_getcap properties-fixed ``` ## To list the supported capability groups ```bash tpm2_getcap -l ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getcommandauditdigest.1.md000066400000000000000000000045201412464516500221540ustar00rootroot00000000000000% tpm2_getcommandauditdigest(1) tpm2-tools | General Commands Manual # NAME **tpm2_getcommandauditdigest**(1) - Retrieve the command audit attestation data from the TPM. # SYNOPSIS **tpm2_getcommandauditdigest** [*OPTIONS*] # DESCRIPTION **tpm2_getcommandauditdigest**(1) - Retrieve the command audit attestation data from the TPM. The attestation data includes the audit digest of the commands in the setlist setup using the command **tpm2_setcommandauditstatus**. Also the attestation data includes the digest of the list of commands setup for audit. The audit digest algorith is setup in the **tpm2_setcommandauditstatus**. # OPTIONS * **-P**, **\--hierarchy-auth**=_AUTH_: Specifies the authorization value for the endorsement hierarchy. * **-c**, **\--key-context**=_OBJECT_: Context object for the signing key that signs the attestation data. * **-p**, **\--auth**=_AUTH_: Specifies the authorization value for key specified by option **-c**. * **-q**, **\--qualification**=_HEX\_STRING\_OR\_PATH_: Data given as a Hex string or binary file to qualify the quote, optional. This is typically used to add a nonce against replay attacks. * **-s**, **\--signature**=_FILE_: Signature output file, records the signature in the format specified via the **-f** option. * **-m**, **\--message**=_FILE_: Message output file, records the quote message that makes up the data that is signed by the TPM. This is the command audit digest attestation data. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. * **-g**, **\--hash-algorithm**: Hash algorithm for signature. Defaults to sha256. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_getcommandauditdigest -P ekpass -c key.ctx -p keypass -m att.data -s att.sig ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_geteccparameters.1.md000066400000000000000000000017711412464516500211320ustar00rootroot00000000000000% tpm2_geteccparameters(1) tpm2-tools | General Commands Manual # NAME **tpm2_geteccparameters**(1) - Retrieves the parameters of an ECC curve identified by its TCG-assigned curveID. # SYNOPSIS **tpm2_geteccparameters** [*OPTIONS*] # DESCRIPTION **tpm2_geteccparameters**(1) - Retrieves the parameters of an ECC curve identified by its TCG-assigned curveID. # OPTIONS * **ARGUMENT**=_ALGORITHM_: Specify the ECC curve. Example ecc521. * **-o**, **\--output**=_FILE_ Specify the file path to save the ECC parameters. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_geteccparameters ecc256 -o ecc.params ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getekcertificate.1.md000066400000000000000000000110131412464516500211040ustar00rootroot00000000000000% tpm2_getekcertificate(1) tpm2-tools | General Commands Manual # NAME **tpm2_getekcertificate**(1) - Retrieve the Endorsement key Certificate. # SYNOPSIS **tpm2_getekcertificate** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_getekcertificate**(1) - Retrieve the endorsement key certificate. The certificate is present either on the TCG specified TPM NV indices OR on the TPM manufacturer's endorsement certificate hosting server. Following are the conditions dictating the certificate location lookup. 1. NV-Index: Default search location when **ARGUMENT** is not specified. 2. Intel-EK-certificate-server: Search location when EK certificate could not be found in the NV index AND tpmEPSgenerated bit is CLEAR AND manufacturer is INTC. 3. Intel-EK-Re-certification-server: Search location when EK certificate could not be found in the NV index AND tpmEPSgenerated bit is SET AND manufacturer is INTC. Note: In this operation information is provided regarding additional software to be run as part of the re-provisioning/ re-certification service. After re-provisioning/ recertification process is complete, EK certificates can be read from the NV indexes by running another instance of **tpm2_getekcertificate**. 4. Generic or other EK-certificate-server: Search location when **ARGUMENT** specifies the EK certificate web hosting address. # OPTIONS * **-o**, **\--ek-certificate**=_FILE_ or _STDOUT_: The file to save the Endorsement key certificate. When EK certificates are found in the TPM NV indices, this option can be specified additional times to save the RSA and ECC EK certificates in order. The tool will warn if additional EK certificates are found on the TPM NV indices and only a single output file is specified. If the option isn't specified all the EK certificates retrieved either from the manufacturer web hosting or from the TPM NV indices, are output to stdout. * **-X**, **\--allow-unverified**: Specifies to attempt connecting with the TPM manufacturer provisioning server without verifying server certificate. This option is irrelevant when EK certificates are found on the TPM NV indices. **WARNING**: This option should be used only on platforms with older CA certificates. * **-u**, **\--ek-public**=_FILE_: Specifies the file path for the endorsement key public portion in tss format. * **-x**, **\--offline**: This flags the tool to operate in an offline mode. In that the certificates can be retrieved for supplied EK public that do not belong to the platform the tool is run on. Useful in factory provisioning of multiple platforms that are not individually connected to the Internet. In such a scenario a single Internet facing provisioning server can utilize this tool in this mode. This forces the tool to not look for the EK certificates on the NV indices. * **--raw**: This flags the tool to output the EK certificate as is received from the source: NV/ Web-Hosting. * **ARGUMENT** the command line argument specifies the URL address for the EK certificate portal. This forces the tool to not look for the EK certificates on the NV indices. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # NOTES When the verbose option is specified, additional curl debugging information is provided by setting the curl mode verbose, see for more information. # EXAMPLES ## Retrieve EK certificate from TPM manufacturer backend by supplying EK public. ```bash tpm2_createek -G rsa -u ek.pub -c key.ctx tpm2_getekcertificate -X -o ECcert.bin -u ek.pub \ https://tpm.manufacturer.com/ekcertserver/ ``` ## Retrieve EK certificate from Intel backend if certificate not found on NV. ```bash tpm2_createek -G rsa -u ek.pub -c key.ctx tpm2_getekcertificate -X -o ECcert.bin -u ek.pub ``` ## Retrieve EK certificate from Intel backend for an offline platform. ```bash tpm2_getekcertificate -X -x -o ECcert.bin -u ek.pub ``` ## Retrieve EK certificate from TPM NV indices only, fail otherwise. ```bash tpm2_getekcertificate -o ECcert.bin ``` ## Retrieve multiple EK certificates from TPM NV indices only, fail otherwise. ```bash tpm2_getekcertificate -o RSA_EK_cert.bin -o ECC_EK_cert.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getpolicydigest.1.md000066400000000000000000000023621412464516500210100ustar00rootroot00000000000000% tpm2_getpolicydigest(1) tpm2-tools | General Commands Manual # NAME **tpm2_getpolicydigest**(1) - Retrieves the policy digest from session. # SYNOPSIS **tpm2_getpolicydigest** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_getpolicydigest**(1) - Returns the policydigest of a session. Output defaults to *stdout* and binary format unless otherwise specified with **-o** and **--hex** options respectively. # OPTIONS * **-o**, **\--output**=_FILE_ Specifies the filename to output the raw bytes to. Defaults to stdout as a hex string. * **\--hex** Convert the output data to hex format without a leading "0x". * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create a session and retrieve policydigest ```bash tpm2 startauthsession -S session.ctx tpm2 policypassword -S session.ctx -L test.policy tpm2 getpolicydigest -S session.ctx -o policy.out tpm2 flushcontext session.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getrandom.1.md000066400000000000000000000045651412464516500176000ustar00rootroot00000000000000% tpm2_getrandom(1) tpm2-tools | General Commands Manual # NAME **tpm2_getrandom**(1) - Retrieves random bytes from the TPM. # SYNOPSIS **tpm2_getrandom** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_getrandom**(1) - Returns the next _SIZE_ octets from the random number generator. The _SIZE_ parameter is expected as the only argument to the tool. Note that the TPM specification recommends that TPM's fix the number of available entry to the maximum size of a hash algorithm output in bytes. Most TPMs do this, and thus the tool verifies that input size is bounded by property **TPM2_PT_MAX_DIGEST** and issues an error if it is too large. Output defaults to *stdout* and binary format unless otherwise specified with **-o** and **--hex** options respectively. # OPTIONS * **-o**, **\--output**=_FILE_ Specifies the filename to output the raw bytes to. Defaults to stdout as a hex string. * **\--hex** Convert the output data to hex format without a leading "0x". * **-f**, **\--force** Override checking that the: - Requested size is within the hash size limit of the TPM. - Number of retrieved random bytes matches requested amount. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption of the parameters. * **\--cphash**=_FILE_: File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, in absence of rphash option, The tool will not actually execute the command, it simply returns a cpHash. * **\--rphash**=_FILE_: File path to record the hash of the response parameters. This is commonly termed as rpHash. * **ARGUMENT** the command line argument specifies the size of the output. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Generate a random 20 bytes and output the binary data to a file ```bash tpm2_getrandom -o random.out 20 ``` ## Generate a random 8 bytes and output the hex formatted data to stdout ```bash tpm2_getrandom 8 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_getsessionauditdigest.1.md000066400000000000000000000050501412464516500222200ustar00rootroot00000000000000% tpm2_getsessionauditdigest(1) tpm2-tools | General Commands Manual # NAME **tpm2_getsessionauditdigest**(1) - Retrieve the command audit attestation data from the TPM. # SYNOPSIS **tpm2_getsessionauditdigest** [*OPTIONS*] # DESCRIPTION **tpm2_getsessionauditdigest**(1) - Retrieve the session audit digest attestation data from the TPM. The attestation data includes the session audit digest and a signature over the session audit digest. The session itself is started with the **tpm2_startauthsession** command. # OPTIONS * **-P**, **\--hierarchy-auth**=_AUTH_: Specifies the authorization value for the endorsement hierarchy. * **-c**, **\--key-context**=_OBJECT_: Context object for the signing key that signs the attestation data. * **-p**, **\--auth**=_AUTH_: Specifies the authorization value for key specified by option **-c**. * **-q**, **\--qualification**=_HEX\_STRING\_OR\_PATH_: Data given as a Hex string or binary file to qualify the quote, optional. This is typically used to add a nonce against replay attacks. * **-s**, **\--signature**=_FILE_: Signature output file, records the signature in the format specified via the **-f** option. * **-m**, **\--message**=_FILE_: Message output file, records the quote message that makes up the data that is signed by the TPM. This is the command audit digest attestation data. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. * **-g**, **\--hash-algorithm**: Hash algorithm for signature. Defaults to sha256. * **-S**, **\--session**=_FILE_: The path of the session that enables and records the audit digests. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -Q -C e -c prim.ctx tpm2_create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2_startauthsession -S session.ctx --audit-session tpm2_getrandom 8 -S session.ctx tpm2_getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_gettestresult.1.md000066400000000000000000000017551412464516500205340ustar00rootroot00000000000000% tpm2_gettestresult(1) tpm2-tools | General Commands Manual # NAME **tpm2_gettestresult**(1) - Get the result of tests performed by the TPM # SYNOPSIS **tpm2_gettestresult** [*OPTIONS*] # DESCRIPTION **tpm2_gettestresult**(1) will return the result of the tests conducted by the TPM. Error code will state if the test executed successfully or have failed. If pending algorithms are scheduled to be tested, **tpm2_gettestresult** will return "TESTING". Otherwise "FAILED" will be returned or "SUCCESS" depending on the result to the test. Manufacturer-dependent information will also be printed in raw hex format. # OPTIONS This tool accepts no tool specific options. [common options](common/options.md) [common tcti options](common/tcti.md) # EXAMPLES ## Get the result of the TPM testing ```bash tpm2_gettestresult ``` # NOTES This command is the one of the few commands authorized to be submitted to TPM when in failure mode. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_gettime.1.md000066400000000000000000000106311412464516500172450ustar00rootroot00000000000000% tpm2_gettime(1) tpm2-tools | General Commands Manual # NAME **tpm2_gettime**(1) - Get the current time and clock from the TPM in a signed form. # SYNOPSIS **tpm2_gettime** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_gettime**(1) - Provides a signed copy of the current time and clock from the TPM. It returns both a signature, and the data in the standard TPM attestation form, a TPMS\_ATTEST structure. It outputs to stdout, in YAML format, the TPMS\_TIME\_INFO structure from the TPM. The structure contains the current setting of Time, Clock, resetCount, and restartCount. The structure is output as YAML defined as: ```yaml time: 13673142 # 64 bit value of time since last _TPM_Init or TPM2_Startup # in ms. clock_info: clock: 13673142 # 64 bit value of time TPM has been powered on in ms. reset_count: 0 # 32 bit value of the number of TPM Resets since the last # TPM2_Clear. restart_count: 0 # 32 bit value of the number of times that TPM2_Shutdown or # _TPM_Hash_Start have occurred since the last TPM Reset or # TPM2_Clear. safe: yes # boolean yes|no value that no value of Clock greater than # the current value of Clock has been previously reported by # the TPM. ``` # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object pointing to the the key used for signing. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--auth**_AUTH_: Optional authorization value to use the key specified by **-c**. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-P**, **\--endorse-auth**_AUTH_: Optional authorization value for the endorsement hierarchy. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the message. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. * **-s**, **\--scheme**=_ALGORITHM_: The signing scheme used to sign the message. Optional. Signing schemes should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Signing Schemes" for a list of supported signature schemes. If specified, the signature scheme must match the key type. If left unspecified, a default signature scheme for the key type will be used. * **-q**, **\--qualification**=_FILE\_OR\_HEX\_STR_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can be either a hex string or path. * **-o**, **\--signature**=_FILE_: The signature file, records the signature structure. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. See section "Signature Format Specifiers". * **--attestation**=_FILE_: The attestation data of the type TPMS_ATTEST signed with signing key. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the file data for sign. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [signature format specifiers](common/signature.md) # EXAMPLES ## Create a key and get attested TPM time ```bash tpm2_createprimary -C e -c primary.ctx tpm2_create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx tpm2_load -C primary.ctx -u rsa.pub -r rsa.priv -c rsa.ctx tpm2_gettime -c rsa.ctx -o attest.sig --attestation attest.data ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_hash.1.md000066400000000000000000000041351412464516500165340ustar00rootroot00000000000000% tpm2_hash(1) tpm2-tools | General Commands Manual # NAME **tpm2_hash**(1) - Performs a hash operation with the TPM. # SYNOPSIS **tpm2_hash** [*OPTIONS*] [*ARGUMENT* OR *STDIN*] # DESCRIPTION **tpm2_hash**(1) - Performs a hash operation on file and returns the results. If argument is not specified, then data is read from stdin. If the results of the hash will be used in a signing operation that uses a restricted signing key, then the ticket returned by this command can indicate that the hash is safe to sign. Output defaults to *stdout* and binary format unless otherwise specified via **-o** and **--hex** options respectively. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Hierarchy to use for the ticket. Defaults to **o**, **TPM_RH_OWNER**, when no value has been specified. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **e** for **TPM_RH_ENDORSEMENT** * **n** for **TPM_RH_NULL** * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hashing algorithm for the digest operation. * **\--hex** Convert the output hmac to hex format without a leading "0x". * **-o**, **\--output**=_FILE_ or _STDOUT_: Optional file to save the hash result. Defaults to stdout in hex form. * **-t**, **\--ticket**=_TICKET\_FILE_ Optional file record of the ticket result. Defaults to stdout in hex form. * **ARGUMENT** or **STDIN** the command line argument specifies the _FILE_ to hash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/alg.md) details the methods for specifying the _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Hash a file with sha1 hash algorithm and save the hash and ticket to a file ```bash tpm2_hash -C e -g sha1 -o hash.bin -t ticket.bin data.txt ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_hierarchycontrol.1.md000066400000000000000000000044571412464516500211770ustar00rootroot00000000000000% tpm2_hierarchycontrol(1) tpm2-tools | General Commands Manual % % July 2019 # NAME **tpm2_hierarchycontrol**(1) - Enable and disable use of a hierarchy and its associated NV storage. # SYNOPSIS **tpm2_hierarchycontrol** [*OPTIONS*] _VARIABLE_ _OPERATION_ # DESCRIPTION **tpm2_hierarchycontrol**(1) - Allows user change phEnable, phEnableNV, shEnable and ehEnable when the proper authorization is provided. Authorization should be one out of owner hierarchy auth, endorsement hierarchy auth and platform hierarchy auth. **As an argument the tool takes the _VARIABLE_ as _TPMA\_STARTUP_CLEAR_ bit and \_OPERATION\_ as string clear|set to clear or set the _VARIABLE_ bit.** Note: If password option is missing, assume NULL. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the handle used to authorize. Defaults to the "platform" hierarchy. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a raw number can be used. * **-P**, **\--hierarchy-auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set phEnableNV with platform hierarchy and its authorization ```bash tpm2_hierarchycontrol -C p phEnableNV set -P pass ``` ## clear phEnableNV with platform hierarchy ```bash tpm2_hierarchycontrol -C p phEnableNV clear ``` ## Set shEnable with platform hierarchy ```bash tpm2_hierarchycontrol -C p shEnable set ``` ## Set shEnable with owner hierarchy ```bash tpm2_hierarchycontrol -C o shEnable set ``` ## Check current TPMA_STARTUP_CLEAR Bits ```bash tpm2_getcap properties-variable ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_hmac.1.md000066400000000000000000000053151412464516500165220ustar00rootroot00000000000000% tpm2_hmac(1) tpm2-tools | General Commands Manual # NAME **tpm2_hmac**(1) - Performs an HMAC operation with the TPM. # SYNOPSIS **tpm2_hmac** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_hmac**(1) - Performs an HMAC operation and returns the results. If argument file is not specified, then data is read from stdin. The hashing algorithm defaults to the keys scheme or sha256 if the key has a NULL scheme. Output defaults to _STDOUT_ and binary format unless otherwise specified via **-o** and **--hex** options respectively. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: The context object of the symmetric signing key providing the HMAC key. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--auth**=_AUTH_: Optional authorization value to use the key specified by **-c**. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm to use. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. * **\--hex** Convert the output hmac to hex format without a leading "0x". * **-o**, **\--output**=_FILE_: Optional file record of the HMAC result. Defaults to _STDOUT_. * **-t**, **\--ticket**=_FILE_: Optional file record of the ticket result. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the file path for the data to HMAC. Defaults to _STDIN_ if not specified. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [authorization formatting](common/alg.md) details the methods for specifying _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Setup ```bash # create a primary object tpm2_createprimary -c primary.ctx # create an hmac key tpm2_create -C primary.ctx -G hmac -c hmac.key ``` ### Perform an HMAC with Default Hash Algorithm Perform an hmac using the key's default scheme (hash algorithm) and output to stdout in hexidecimal format. ```bash tpm2_hmac -c hmac.key --hex data.in e6eda48a53a9ddbb92f788f6d98e0372d63a408afb11aca43f522a2475a32805 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_import.1.md000066400000000000000000000121051412464516500171170ustar00rootroot00000000000000% tpm2_import(1) tpm2-tools | General Commands Manual # NAME **tpm2_import**(1) - Imports an external key into the tpm as a TPM managed key object. # SYNOPSIS **tpm2_import** [*OPTIONS*] # DESCRIPTION **tpm2_import**(1) - Imports an external generated key as TPM managed key object. It requires that the parent key object be a RSA key. Can also import a TPM managed key object created by the tpm2_duplicate tool. # OPTIONS These options control the key importation process: * **-G**, **\--key-algorithm**=_ALGORITHM_: The algorithm used by the key to be imported. Supports: * **aes** - AES 128, 192 or 256 key. * **rsa** - RSA 1024 or 2048 key. * **ecc** - ECC NIST P192, P224, P256, P384 or P521 public and private key. * **hmac** - HMAC key. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm for generating the objects name. This is optional and defaults to **sha256** when not specified. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. * **-i**, **\--input**=_FILE_: Specifies the filename of the key to be imported. For AES keys, this file is the raw key bytes. For assymetric keys in PEM or DER format. A typical file is generated with `openssl genrsa`. * **-C**, **\--parent-context**=_OBJECT_: The parent key object. * **-U**, **\--parent-public**=_FILE_: Optional. Specifies the parent key public data file input. This can be read with **tpm2_readpublic**(1) tool. If not specified, the tool invokes a tpm2_readpublic on the parent object. * **-k**, **\--encryption-key**=_FILE_: Optional. Specifies the file containing the symmetric algorithm key that was used for the inner wrapper. If the file is specified the tool assumes the algorithm is AES 128 in CFB mode otherwise none. * **-r**, **\--private**=_FILE_: Specifies the file path required to save the encrypted private portion of the object imported as key. When importing a duplicated object this option specifies the file containing the private portion of the object to be imported. [protection details](common/protection-details.md) * **-u**, **\--public**=_FILE_: Specifies the file path required to save the public portion of the object imported as key When importing a duplicated object this option specifies the file containing the public portion of the object to be imported. * **-a**, **\--attributes**=_ATTRIBUTES_: The object attributes, optional. * **-P**, **\--parent-auth**=_AUTH_: The authorization value for using the parent key specified with **-C**. * **-p**, **\--key-auth**=_AUTH_: The authorization value for the imported key, optional. * **-L**, **\--policy**=_POLICY\_FILE_: The policy file. * **-s**, **\--seed**=_FILE_: Specifies the file containing the encrypted seed of the duplicated object. * **\--passin**=_OSSL\_PEM\_FILE\_PASSWORD_ An optional password for an Open SSL (OSSL) provided input file. It mirrors the -passin option of OSSL and is known to support the pass, file, env, fd and plain password formats of openssl. (see *man(1) openssl*) for more. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [object attribute specifiers](common/obj-attrs.md) details the options for specifying the object attributes _ATTRIBUTES_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## To import a key, one needs to have a parent key ```bash tpm2_createprimary -Grsa2048:aes128cfb -C o -c parent.ctx ``` Create your key and and import it. If you already have a key, just use that and skip creating it. ## Import an AES 128 key ```bash dd if=/dev/urandom of=sym.key bs=1 count=16 tpm2_import -C parent.ctx -G aes -i sym.key -u key.pub -r key.priv ``` ## Import an RSA key ```bash openssl genrsa -out private.pem 2048 tpm2_import -C parent.ctx -G rsa -i private.pem -u key.pub -r key.priv ``` ## Import an ECC key ```bash openssl ecparam -name prime256v1 -genkey -noout -out private.ecc.pem tpm2_import -C parent.ctx -G ecc -i private.ecc.pem -u key.pub -r key.priv ``` ## Import a duplicated key ```bash tpm2_import -C parent.ctx -i key.dup -u key.pub -r key.priv -L policy.dat ``` # LIMITATIONS * The TPM requires that the name algorithm of the child be smaller than the parent. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_incrementalselftest.1.md000066400000000000000000000053041412464516500216630ustar00rootroot00000000000000% tpm2_incrementalselftest(1) tpm2-tools | General Commands Manual # NAME **tpm2_incrementalselftest**(1) - Request testing of specified algorithm list # SYNOPSIS **tpm2_incrementalselftest** [*OPTIONS*] _ALG\_SPEC\_LIST_ # DESCRIPTION **tpm2_incrementalselftest**(1) Request the TPM to perform testing on specified algorithm and print a list of algorithm scheduled to be tested *OR* remain to be tested but not scheduled. The main interest of this command is to reduce delays that might occur on cryptographic operations as TPM must test the algorithm prior using it. # ALG\_SPEC\_LIST A space-separated list of algorithm suite to be tested. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. If _ALG\_SPEC\_LIST_ is left empty, **tpm2_incrementalselftest**(1) will return the list of algorithms left to be tested. Please note that in this case these algorithms are **NOT** scheduled to be tested. If _ALG\_SPEC\_LIST_ is not empty, **tpm2_incrementalselftest**(1) will return the list of algorithms that remains to be tested. This list contains algorithms scheduled for testing AND algorithms that remains to be tested and not yet scheduled. This can occur for instance if all AES mode have not been already tested yet. # Output List of algorithms to be tested (implying scheduled) or remain to be tested (not scheduled) is also printed in YAML format. If none of the specified algorithm is printed, that means both that they are already tested AND that these algorithms won't be tested again. # OPTIONS This tool accepts no tool specific options. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Request testing of RSA algorithm ```bash tpm2_incrementalselftest rsa ``` ## Request testing of multiple algorithms ```bash tpm2_incrementalselftest rsa ecc xor aes cbc ``` # NOTES Algorithm suite specified can imply either testing the combination or the complete suite, depending on TPM manufacturer implementation. e.g : One TPM might only test AES with CTR mode if "aes ctr" is specified. An other might also test complete AES mode list AND test ctr mode. If an algorithm has already been tested, this command won't permit re-executing the test. Only issuing **tpm2_selftest**(1) in full-test mode enabled will force re-testing. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_load.1.md000066400000000000000000000052251412464516500165310ustar00rootroot00000000000000% tpm2_load(1) tpm2-tools | General Commands Manual # NAME **tpm2_load**(1) - Load an object into the TPM. # SYNOPSIS **tpm2_load** [*OPTIONS*] # DESCRIPTION **tpm2_load**(1) - Load both the private and public portions of an object into the TPM. The tool outputs the name of the loaded object in a YAML dictionary format with the key *name* where the value for that key is the name of the object in hex format, for example: ```yaml name: 000bac25cb8743111c8e1f52f2ee7279d05d3902a18dd1af694db5d1afa7adf1c8b3 ``` It also saves a context file for future interactions with the object. **NOTE**: Both private and public portions of the tpm key must be specified. # OPTIONS * **-C**, **\--parent-context**=_OBJECT_: The parent object. * **-P**, **\--auth**=_AUTH_: The authorization value of the parent object specified by **-C**. * **-u**, **\--public**=_FILE_: A file containing the public portion of the object. * **-r**, **\--private**=_FILE_: A file containing the sensitive portion of the object. * **-n**, **\--name**=_FILE_: An optional file to save the name structure of the object. * **-c**, **\--key-context**=_FILE_: The file name of the saved object context, required. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Setup To load an object you first must create an object under a primary object. So the first step is to create the primary object. ```bash tpm2_createprimary -c primary.ctx ``` Step 2 is to create an object under the primary object. ```bash tpm2_create -C primary.ctx -u key.pub -r key.priv ``` This creates the private and public portions of the TPM object. With these object portions, it is now possible to load that object into the TPM for subsequent use. ## Loading an Object into the TPM The final step, is loading the public and private portions of the object into the TPM. ```bash tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx name: 000bac25cb8743111c8e1f52f2ee7279d05d3902a18dd1af694db5d1afa7adf1c8b3 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_loadexternal.1.md000066400000000000000000000142241412464516500202730ustar00rootroot00000000000000% tpm2_loadexternal(1) tpm2-tools | General Commands Manual # NAME **tpm2_loadexternal**(1) - Load an external object into the TPM. # SYNOPSIS **tpm2_loadexternal** [*OPTIONS*] # DESCRIPTION **tpm2_loadexternal**(1) - This command loads an external object into the TPM, forgoing TPM protections. Ie, the key material is not protected by the parent object's seed. The command allows loading of just the public portion of an object or both the public and private portions of an object. The tool outputs the name of the loaded object in a YAML dictionary format with the key *name* where the value for that key is the name of the object in hex format, for example: ```yaml name: 000bac25cb8743111c8e1f52f2ee7279d05d3902a18dd1af694db5d1afa7adf1c8b3 ``` It also saves a context file for future interactions with the object. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Hierarchy to use for the ticket, optional. Defaults to **n**, **null**. Supported options are: * **o** for the **owner** hierarchy. * **p** for the **platform** hierarchy. * **e** for the **endorsement** hierarchy. * **n** for the **null** hierarchy. * **-G**, **\--key-algorithm**=_ALGORITHM_: The algorithm used by the key to be imported. Supports: * **aes** - AES 128,192 or 256 key. * **rsa** - RSA 1024 or 2048 key. * **ecc** - ECC NIST P192, P224, P256, P384 or P521 public and private key. * **-u**, **\--public**=_FILE_: The public portion of the object, this can be one of the following file formats: * TSS - The TSS/TPM format. For example from option `-u` of command **tpm2_create**(1). * RSA - OSSL PEM formats. For example `public.pem` from the command `openssl rsa -in private.pem -out public.pem -pubout` * ECC - OSSL PEM formats. For example `public.pem` from the command `openssl ec -in private.ecc.pem -out public.ecc.pem -pubout` * **-r**, **\--private**=_FILE_: The sensitive portion of the object, optional. If one wishes to use the private portion of a key, this must be specified. Like option **-u**, this command takes files in the following format: * RSA - OSSL PEM formats. For example `private.pem` from the command `openssl genrsa -out private.pem 2048` Since an RSA public key can be derived from the private PEM file, their is no need to specify -u for the public portion. *Note*: The private portion does not respect TSS formats as it's impossible to get a **TPM2B_SENSITIVE** output from a previous command. They are always protected by the TPM as **TPM2B_PRIVATE** blobs. * **-p**, **\--auth**=_AUTH_: The authorization value for the key, optional. * **-L**, **\--policy**=_POLICY\_FILE_: The input policy file, optional. A file containing the hash of a policy derived from `tpm2_createpolicy`. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm for generating the objects name. This is optional and defaults to sha256 when not specified. However, load external supports having a *null* name algorithm. In this case, no cryptographic binding checks between the public and private portions are performed. * **-a**, **\--attributes**=_ATTRIBUTES_: The object attributes, optional. The default for created objects is: `TPMA_OBJECT_SIGN_ENCRYPT|TPMA_OBJECT_DECRYPT`. Optionally, if -p is specified or no `-p` or `-L` is specified then `TPMA_OBJECT_USERWITHAUTH` is added to the default attribute set. *Note*: If specifying attributes, the TPM will reject certain attributes like **TPMA_OBJECT_FIXEDTPM**, as those guarantees cannot be made. * **-c**, **\--key-context**=_FILE_ The file name to save the object context, required. * **-n**, **\--name**=_FILE_: An optional file to save the object name, which is in a binary hash format. The size of the hash is based on name algorithm or the **-g** option. * **\--passin**=_OSSL\_PEM\_FILE\_PASSWORD_ An optional password for an Open SSL (OSSL) provided input file. It mirrors the -passin option of OSSL and is known to support the pass, file, env, fd and plain password formats of openssl. (see *man(1) openssl*) for more. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [object attribute specifiers](common/obj-attrs.md) details the options for specifying the object attributes _ATTRIBUTES_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # NOTES * If the hierarchy is *null* or the name hashing algorithm is *null*, tickets produced using the object will be NULL. * If the private portion of an object is specified, the hierarchy must be *null* or the TPM will reject loading it. # EXAMPLES ## Load a TPM generated public key into the *owner* hierarchy ```bash tpm2_createprimary -c primary.ctx tpm2_create -C primary.ctx -u pub.dat -r priv.dat tpm2_loadexternal -C o -u pub.dat -c pub.ctx name: 000b9be4d7c6193a57e1bfc86a42a6b03856a91d2f9e77c6cbdb796a783d52d4b3b9 ``` ## Load an RSA public key into the *owner* hierarchy ```bash openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -out public.pem -outform PEM -pubout tpm2_loadexternal -C o -Grsa -u public.pem -c key.ctx name: 000b7b91d304d16995d42792b57d0fb25df7abe5fdd8afe9950730e00dc5b934ddbc ``` ## Load an RSA key-pair into the *null* hierarchy ```bash openssl genrsa -out private.pem 2048 tpm2_loadexternal -C n -Grsa -r private.pem -c key.ctx name: 000b635ea220b6c62ec1d02343859dd203c8ac5dad82ebc5b124e407d2502f88691f ``` ## Load an AES key into the *null* hierarchy ```bash dd if=/dev/urandom of=sym.key bs=1 count=16 tpm2_loadexternal -C n -Gaes -r sym.key -c key.ctx name: 000bfc4d8dd7e4f921bcc9dca4b04f49564243cd9def129a3740002bfd4b9e966d34 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_makecredential.1.md000066400000000000000000000060361412464516500205630ustar00rootroot00000000000000% tpm2_makecredential(1) tpm2-tools | General Commands Manual # NAME **tpm2_makecredential**(1) - Generate the encrypted-user-chosen-data and the wrapped-secret-data-encryption-key for the privacy-sensitive credentialing process of a TPM object. # SYNOPSIS **tpm2_makecredential** [*OPTIONS*] # DESCRIPTION **tpm2_makecredential**(1) - The TPM supports a privacy preserving protocol for distributing credentials for keys on a TPM. The process guarantees that the credentialed-TPM-object(AIK) is loaded on the same TPM as a well-known public-key-object(EK) without knowledge of the specific public properties of the credentialed-TPM-object(AIK). The privacy is guaranteed due to the fact that only the name of the credentialed-TPM-object(AIK) is shared and not the credentialed-TPM-object's public key itself. Make-credential is the first step in this process where in after receiving the public-key-object(EK) public key of the TPM and the name of the credentialed-TPM-object(AIK), an encrypted-user-chosen-data is generated and the secret-data-encryption-key is generated and wrapped using cryptographic processes specific to credential activation that guarantees that the credentialed-TPM-object(AIK) is loaded on the TPM with the well-known public-key-object(EK). **tpm2_makecredential** can be used to generate the encrypted-user-chosen-data and the wrapped secret-data-encryption-key without a TPM by using the **none** TCTI option. # OPTIONS * **-e**, **\--encryption-key**=_FILE_: **DEPRECATED**, use **-u** or **--public** instead. * **-u**, **\--public**=_FILE_: A TPM public key which was used to wrap the seed. NOTE: This option is same as **-e** and is added to make it similar with other tools specifying the public key. The old option is retained for backwards compatibility. * **-G**, **\--key-algorithm**=_ALGORITHM_: The key algorithm associated with TPM public key. Specify either RSA/ ECC. When this option is used, input public key is expected to be in PEM format and the default TCG EK template is used for the key properties. * **-s**, **\--secret**=_FILE_ or _STDIN_: The secret which will be protected by the key derived from the random seed. It can be specified as a file or passed from stdin. * **-n**, **\--name**=_FILE_: The name of the key for which certificate is to be created. * **-o**, **\--credential-blob**=_FILE_: The output file path, recording the encrypted-user-chosen-data and the wrapped secret-data-encryption-key. [common options](common/options.md) [common tcti options](common/tcti.md) # EXAMPLES ```bash tpm2 createek -Q -c 0x81010009 -G rsa -u ek.pub tpm2 createak -C 0x81010009 -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \ -n ak.name -p akpass> ak.out file_size=`ls -l ak.name | awk {'print $5'}` loaded_key_name=`cat ak.name | xxd -p -c $file_size` tpm2 readpublic -c 0x81010009 -o ek.pem -f pem -Q echo "12345678" | tpm2 makecredential -Q -u ek.pem -s - -n $loaded_key_name \ -o mkcred.out -G rsa ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvcertify.1.md000066400000000000000000000066651412464516500176340ustar00rootroot00000000000000% tpm2_nvcertify(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvcertify**(1) - Provides attestation of the contents of an NV index. # SYNOPSIS **tpm2_nvcertify** [*OPTIONS*] [*ARGUMENTS*] # DESCRIPTION **tpm2_nvcertify**(1) - Provides attestation of the contents of an NV index. NOTE: As part of the attestation output, the NV index contents are revealed. # OPTIONS These options control the certification: * **-C**, **\--signingkey-context**=_OBJECT_: The key object that signs the attestation structure. * **-P**, **\--signingkey-auth**=_AUTH_: The authorization value provided for the object specified with -C. * **-c**, **\--nvauthobj-context**=_OBJECT_: The object that is the authorization handle for the NV object. It is either the NV index handle itself or the platform/ owner hierarchy handle. If not specified it defaults to the NV index handle. * **-p**, **\--nvauthobj-auth**=_AUTH_: The authorization value provided for the object specified with -c. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm to use in signature generation. * **-s**, **\--scheme**=_ALGORITHM_: The signing scheme used to sign the attestation data. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. * **-o**, **\--signature**=_FILE_: Output file name for the signature data. * **-q**, **\--qualification**=_FILE\_OR\_HEX\_STR_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can be either a hex string or path. * **\--size**=_NATURAL_NUMBER_: Specifies the size of data to be read in bytes, starting from 0 if offset is not specified. If not specified, the size of the data as reported by the public portion of the index will be used. * **\--offset**=_NATURAL_NUMBER_: The offset within the NV index to start reading from. * **--attestation**=_FILE_: The attestation data of the type TPM2_CREATION_INFO signed with signing key. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_nvdefine -s 32 -a "authread|authwrite" 1 dd if=/dev/urandom bs=1 count=32 status=none| \ tpm2_nvwrite 1 -i- tpm2_createprimary -C o -c primary.ctx -Q tpm2_create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx -c signing_key.ctx -Q tpm2_readpublic -c signing_key.ctx -f pem -o sslpub.pem -Q tpm2_nvcertify -C signing_key.ctx -g sha256 -f plain -s rsassa \ -o signature.bin --attestation attestation.bin --size 32 1 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvdefine.1.md000066400000000000000000000101021412464516500173760ustar00rootroot00000000000000% tpm2_nvdefine(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvdefine**(1) - Define a TPM Non-Volatile (NV) index. # SYNOPSIS **tpm2_nvdefine** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvdefine**(1) - Define an NV index with given auth value. The index is specified as an argument. It can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". If an index isn't specified, the tool uses the first free index. The tool outputs the nv index defined on success. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the handle used to authorize. Defaults to **o**, **TPM_RH_OWNER**, when no value has been specified. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. * **-s**, **\--size**=_NATURAL_NUMBER_: Specifies the size of data area in bytes. Defaults to **MAX_NV_INDEX_SIZE** which is typically 2048. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to compute the name of the Index and used for the authorization policy. If the index is an extend index, the hash algorithm is used for the extend. * **-a**, **\--attributes**=_ATTRIBUTES_ Specifies the attribute values for the nv region used when creating the entity. Either the raw bitfield mask or "nice-names" may be used. See section "NV Attributes" for more details. If not specified, the attributes default to various selections based on the hierarchy the index is defined in. For the owner hiearchy the defaults are: - TPMA_NV_OWNERWRITE - TPMA_NV_OWNERREAD For the platform hiearchy, the defaults are: - TPMA_NV_PPWRITE - TPMA_NV_PPREAD If a policy file is specified, the hiearchy chosen default attributes are bitwise or'd with: - TPMA_NV_POLICYWRITE - TPMA_NV_POLICYREAD If a policy file is **NOT** specified, the hiearchy chosen default attributes are bitwise or'd with: - TPMA_NV_AUTHWRITE - TPMA_NV_AUTHREAD * **-P**, **\--hierarchy-auth**=_AUTH_: Specifies the authorization value for the hierarchy. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-p**, **\--index-auth**=_AUTH_: Specifies the password of NV Index when created. HMAC and Password authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-L**, **\--policy**=_FILE_: Specifies the policy digest file for policy based authorizations. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption/decryption of the parameters. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [object attribute specifiers](common/nv-attrs.md) details the options for specifying the nv attributes _ATTRIBUTES_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_nvdefine 0x1500016 -C o -s 32 -a 0x2000A tpm2_nvdefine 0x1500016 -C o -s 32 -a ownerread|ownerwrite|policywrite -p 1a1b ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvextend.1.md000066400000000000000000000054531412464516500174500ustar00rootroot00000000000000% tpm2_nvextend(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvextend**(1) - Extend an Non-Volatile (NV) index like it was a PCR. # SYNOPSIS **tpm2_nvextend** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvextend**(1) - Extend an Non-Volatile (NV) index like it was a PCR. The NV index must be of type "extend" which is specified via the "nt" field when creating the NV space with tpm2_nvdefine(1). The index can be specified as raw handle or an offset value to the NV handle range "TPM2_HR_NV_INDEX" as an argument. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-i**, **\--input**=_FILE_: Specifies the input file with data to extend to the NV index. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption/decryption of the parameters. * **-n**, **\--name**=_FILE_: The name of the NV index that must be provided when only calculating the cpHash without actually dispatching the command to the TPM. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## OR 0xbadc0de into an index of 0's ```bash tpm2_nvdefine -C o -a "nt=extend|ownerread|policywrite|ownerwrite|writedefine" 1 echo 'my data' | tpm2_nvextend -C o -i- 1 tpm2_nvread -C o 1 | xxd -p -c32 db7472e3fe3309b011ec11565bce4ea6668cc8ecdef7e6fdcda5206687af3f43 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvincrement.1.md000066400000000000000000000037451412464516500201470ustar00rootroot00000000000000% tpm2_nvincrement(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvincrement**(1) - Increment counter in a Non-Volatile (NV) index. # SYNOPSIS **tpm2_nvincrement** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvincrement**(1) - Increment value of a Non-Volatile (NV) index setup as a counter. The index can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## To increment the counter at index *0x150016* ```bash tpm2_nvdefine -C o -s 8 -a "ownerread|authread|authwrite|nt=1" 0x1500016 -p index tpm2_nvincrement -C 0x1500016 0x1500016 -P "index" tpm2_nvread 0x1500016 -P index | xxd -p ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvread.1.md000066400000000000000000000055561412464516500171000ustar00rootroot00000000000000% tpm2_nvread(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvread**(1) - Read the data stored in a Non-Volatile (NV)s index. # SYNOPSIS **tpm2_nvread** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvread**(1) - Read the data stored in a Non-Volatile (NV)s index. The index can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-o**, **\--output**=_FILE_: File to write data * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-s**, **\--size**=_NATURAL_NUMBER_: Specifies the size of data to be read in bytes, starting from 0 if offset is not specified. If not specified, the size of the data as reported by the public portion of the index will be used. * **\--offset**=_NATURAL_NUMBER_: The offset within the NV index to start reading from. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-n**, **\--name**=_FILE_: The name of the NV index that must be provided when only calculating the cpHash without actually dispatching the command to the TPM. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules.d) # EXAMPLES ## Read 32 bytes from an index starting at offset 0 ```bash tpm2_nvdefine -C o -s 32 -a "ownerread|policywrite|ownerwrite" 1 echo "please123abc" > nv.dat tpm2_nvwrite -C o -i nv.dat 1 tpm2_nvread -C o -s 32 1 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvreadlock.1.md000066400000000000000000000041241412464516500177370ustar00rootroot00000000000000% tpm2_nvreadlock(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvreadlock**(1) - Lock the Non-Volatile (NV) index for further reads. # SYNOPSIS **tpm2_nvreadlock** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvreadlock**(1) - Lock the Non-Volatile (NV) index for further reads. The lock on the NN index is unlocked when the TPM is restarted and the NV index becomes readable again. The index can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Lock an index ```bash tpm2_nvdefine -Q 1 -C o -s 32 \ -a "ownerread|policywrite|ownerwrite|read_stclear" echo "foobar" > nv.readlock tpm2_nvwrite -Q 0x01000001 -C o -i nv.readlock tpm2_nvread -Q 1 -C o -s 6 -o 0 tpm2_nvreadlock -Q 1 -C o ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvreadpublic.1.md000066400000000000000000000023711412464516500202670ustar00rootroot00000000000000% tpm2_nvreadpublic(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvreadpublic**(1) - Display all defined Non-Volatile (NV)s indices. # SYNOPSIS **tpm2_nvreadpublic** [*OPTIONS*] # DESCRIPTION **tpm2_nvreadpublic**(1) - Display all defined Non-Volatile (NV)s indices to stdout in a YAML format. Display metadata for all defined NV indices. Metadata includes: * The size of the defined region. * The hash algorithm used to compute the name of the index. * The auth policy. * The NV attributes as defined in section "NV Attributes". ## Example Output ``` 0x1500015: hash algorithm: friendly: sha256 value: 0xB attributes: friendly: ownerwrite|ownerread value: 0x2000200 size: 32 authorization policy: 0x1500017: hash algorithm: friendly: sha256 value: 0xB attributes: friendly: ownerwrite|ownerread value: 0x2000200 size: 32 authorization policy: ``` # OPTIONS This tool takes no tool specific options. [common options](common/options.md) [common tcti options](common/tcti.md) [nv attributes](common/nv-attrs.md) # EXAMPLES ## List the defined NV indices to stdout ```bash tpm2_nvreadpublic ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvsetbits.1.md000066400000000000000000000053221412464516500176310ustar00rootroot00000000000000% tpm2_nvsetbits(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvsetbits**(1) - Bitwise OR bits into a Non-Volatile (NV). # SYNOPSIS **tpm2_nvsetbits** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvsetbits**(1) - Bitwise OR bits into a Non-Volatile (NV). The NV index must be of type "bits" which is specified via the "nt" field when creating the NV space with tpm2_nvdefine(1). The index can be specified as raw handle or an offset value to the NV handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-i**, **\--bits**=_BITS_: Specifies the bit value as a number to bitwise OR into the current value of the NV index. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. This can be used to specify an auxiliary session for auditing and or encryption/decryption of the parameters. * **-n**, **\--name**=_FILE_: The name of the NV index that must be provided when only calculating the cpHash without actually dispatching the command to the TPM. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## OR 0xbadc0de into an index of 0's ```bash tpm2_nvdefine -C o -a "nt=bits|ownerread|policywrite|ownerwrite|writedefine" 1 tpm2_nvsetbits -C o -i 0xbadc0de 1 tpm2_nvread -C o 1 | xxd -p | sed s/'^0*'/0x/ 0xbadc0de ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvundefine.1.md000066400000000000000000000053231412464516500177520ustar00rootroot00000000000000% tpm2_nvundefine(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvundefine**(1) - Delete a Non-Volatile (NV) index. # SYNOPSIS **tpm2_nvundefine** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvundefine**(1) - Deletes a Non-Volatile (NV) index that was previously defined with **tpm2_nvdefine**(1). The index is specified as an argument. It can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". The tool is also capable of deleting NV indices with attribute `TPMA_NV_POLICY_DELETE`, and the tool uses this attribute for the default hierarchy to select when `-C` is missing. The default value for `-C` is the "owner" hierarchy when `TPMA_NV_POLICY_DELETE` is clear and "platform" when `TPMA_NV_POLICY_DELETE` is set. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle may be specified. * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-S**, **\--session**=_POLICY_SESSION_: Specify a policy session to use when the NV index has attribute `TPMA_NV_POLICY_DELETE` set. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Define an ordinary NV index and delete it ```bash tpm2_nvdefine 1 tpm2_nvundefine 1 ``` ## Define an ordinary NV index with attribute `TPMA_NV_POLICY_DELETE` and delete it ```bash tpm2_startauthsession -S s.ctx tpm2_policyauthvalue -S s.ctx tpm2_policycommandcode -S s.ctx -L policy.dat TPM2_CC_NV_UndefineSpaceSpecial tpm2_nvdefine -C p -s 32 \ -a "ppread|ppwrite|authread|authwrite|platformcreate|policydelete|write_stclear|read_stclear" \ -L policy.dat 1 tpm2_flushcontext s.ctx tpm2_startauthsession --policy-session -S s.ctx tpm2_policyauthvalue -S s.ctx tpm2_policycommandcode -S s.ctx TPM2_CC_NV_UndefineSpaceSpecial tpm2_nvundefine -S s.ctx 1 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvwrite.1.md000066400000000000000000000044321412464516500173070ustar00rootroot00000000000000% tpm2_nvwrite(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvwrite**(1) - Write data to a Non-Volatile (NV) index. # SYNOPSIS **tpm2_nvwrite** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvwrite**(1) - Write data specified via _FILE_ to a Non-Volatile (NV) index. If _FILE_ is not specified, it defaults to stdin. The index is specified as an argument and can be a raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **ARGUMENT**=_NUMBER_ Specify the NV index to write to as an offset to the starting NV index range or an absolute index value. Example: tpm2_nvwrite 1 is same as tpm2_nvwrite 0x01000001 * **-i**, **\--input**=_FILE_: Specifies the input file with data to write to NV. * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **\--offset**=_NATURAL_NUMBER_: The offset within the NV index to start writing at. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Write the file nv.data to index *0x01000001* ```bash tpm2_nvdefine -Q 1 -C o -s 32 -a "ownerread|policywrite|ownerwrite" echo "please123abc" > nv.test_w tpm2_nvwrite -Q 1 -C o -i nv.test_w ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_nvwritelock.1.md000066400000000000000000000047371412464516500201700ustar00rootroot00000000000000% tpm2_nvwritelock(1) tpm2-tools | General Commands Manual # NAME **tpm2_nvwritelock**(1) - Lock the Non-Volatile (NV) index for further writes. # SYNOPSIS **tpm2_nvwritelock** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_nvwritelock**(1) - Lock the Non-Volatile (NV) index for further writes. The lock on the NV index is unlocked when the TPM is restarted and the NV index becomes writable again. The index can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **\--global**: Lock all NV indices with attribute TPMA\_NV\_GLOBALLOCK. This option does not require an NV index or offset as an argument. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the NV index or offset number. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Lock an index ```bash tpm2_nvdefine -C o -s 32 \ -a "ownerread|policywrite|ownerwrite|writedefine" 1 echo "foobar" > nv.writelock tpm2_nvwrite -C o -i nv.writelock 1 tpm2_nvwritelock -C o 1 # fails with "NV access locked" tpm2_nvwrite -C o -i nv.writelock 1 ``` ## Global Lock ```bash tpm2_nvdefine -C o -s 32 \ -a "ownerread|policywrite|ownerwrite|globallock" 1 tpm2_nvwritelock -C o --global # this command fails with "NV access locked". echo foo | tpm2_nvwrite -C o -i- 1 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_pcrallocate.1.md000066400000000000000000000043521412464516500201030ustar00rootroot00000000000000% tpm2_pcrallocate(1) tpm2-tools | General Commands Manual # NAME **tpm2_pcrallocate**(1) - Configure PCRs and bank algorithms. # SYNOPSIS **tpm2_pcrallocate** [*OPTIONS*] [*ARGUMENT] # DESCRIPTION **tpm2_pcrallocate**(1) - Allow the user to specify a PCR allocation for the TPM. An allocation is the enabling or disabling of PCRs and it's banks. A PCR can have multiple banks, where each bank is associated with a specific hashing algorithm. Allocation is specified in the argument. If no allocation is given, then SHA1 and SHA256 banks with PCRs 0 - 23 are allocated. Allocation is a list of banks and selected pcrs. The values should follow the pcr bank specifiers standards, see section "PCR Bank Specifiers". The new allocations become effective after the next reboot. **Note**: This command requires platform authorization. # OPTIONS * **-P**, **\--auth**=_AUTH_: Optional authorization value. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **ARGUMENT** the command line argument specifies the PCR allocation. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [object attribute specifiers](common/obj-attrs.md) details the options for specifying the object attributes _ATTRIBUTES_. [pcr bank specifiers](common/pcr.md) details the syntax for specifying pcr list. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## To allocate the two default banks (SHA1 and SHA256) ```bash tpm2_pcrallocate ``` ## To make a custom allocation with a platform authorization ```bash tpm2_pcrallocate -P abc sha1:7,8,9,10,16,17,18,19+sha256:all ``` ## To completly switch from SHA1 bank to SHA256 with a platform authorization ```bash tpm2_pcrallocate -P abc sha1:none+sha256:all ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_pcrevent.1.md000066400000000000000000000026021412464516500174340ustar00rootroot00000000000000% tpm2_pcrevent(1) tpm2-tools | General Commands Manual # NAME **tpm2_pcrevent**(1) - Hashes a file and optionally extends a pcr. # SYNOPSIS **tpm2_pcrevent** [*OPTIONS*] _FILE_ _PCR\_INDEX_ # DESCRIPTION **tpm2_pcrevent**(1) - Hashes _FILE_ if specified or stdin. It uses all of the hashing algorithms that the TPM supports. Optionally, if a PCR index is specified, it extends that PCR for all supported algorithms with the hash digest. _FILE_ and _PCR\_INDEX\_ arguments don't need to come in any particular order. In either case, it outputs to stdout the hash algorithm used and the digest value, one per line: _alg_:_digest_ Where _alg_ is the algorithm used (like sha1) and _digest_ is the digest resulting from the hash computation of _alg_ on the data. See sections 23.1 and sections 17 of the [TPM2.0 Specification](https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf) # OPTIONS These options control extending the pcr: * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for PCR. [common options](common/options.md) [common tcti options](common/tcti.md) [authorization formatting](common/authorizations.md) # EXAMPLES ## Hash a file ```bash echo "foo" > data tpm2_pcrevent data ``` ## Hash a file and extend PCR 8 ```bash echo "foo" > data tpm2_pcrevent 8 data ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_pcrextend.1.md000066400000000000000000000033331412464516500176040ustar00rootroot00000000000000% tpm2_pcrextend(1) tpm2-tools | General Commands Manual # NAME **tpm2_pcrextend**(1) - Extends a PCR. # SYNOPSIS **tpm2_pcrextend** [*OPTIONS*] _PCR\_DIGEST\_SPEC_ # DESCRIPTION **tpm2_pcrextend**(1) - Extends the pcrs with values indicated by _PCR\_DIGEST\_SPEC_. A _PCR\_DIGEST\_SPEC_ is defined as follows: * A numerical PCR identifier. * A colon followed by the algorithm hash specification. The algorithm hash specification is as follows: * The algorithm friendly name or raw numerical. * An equals sign. * The hex hash value. ### Example Digest Specification ``` 4:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 ``` **Note**: Multiple specifications of PCR and hash are allowed. Multiple hashes cause the PCR to be extended with both hashes. Multiple same PCR values cause the PCR to be extended multiple times. Extension is done in order from left to right as specified. At most 5 hash extensions per PCR entry are supported. This is to keep the parser simple. # OPTIONS This tool accepts no tool specific options. [common options](common/options.md) [common tcti options](common/tcti.md) [PCR bank specifiers](common/pcr.md) # EXAMPLES ## Extend PCR 4's SHA1 bank with a hash ```bash tpm2_pcrextend 4:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 ``` ## Extend PCR 4's SHA1 and SHA256 banks with hashes ```bash tpm2_pcrextend 4:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15,sha256=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c ``` ## Extend PCR 4's SHA1 and PCR 7's SHA256 bank with hashes ```bash tpm2_pcrextend 4:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 7:sha256=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_pcrread.1.md000066400000000000000000000043031412464516500172260ustar00rootroot00000000000000% tpm2_pcrread(1) tpm2-tools | General Commands Manual # NAME **tpm2_pcrread**(1) - List PCR values. # SYNOPSIS **tpm2_pcrread** [*OPTIONS*] _PCR\_LIST\_OR\_ALG_ # DESCRIPTION **tpm2_pcrread**(1) - Displays PCR values. Without any arguments, **tpm2_pcrread**(1) outputs all PCRs and their hash banks. One can use specify the hash algorithm or a pcr list as an argument to filter the output. To only output PCR banks with a given algorithm, specify the hashing algorithm as the argument. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. To output a list of PCR banks (sha1, sha256, etc) and ids (0, 1, 2 etc) specify a PCR selection list as the argument as specified via section "PCR Bank Specifiers". Also read **NOTES** section below. Output is written in a YAML format to stdout, with each algorithm followed by a PCR index and its value. As a simple example assume just sha1 and sha256 support and only 1 PCR. The output would be: ``` $ tpm2_pcrread sha1:0+sha256:0 sha1 : 0 : 0000000000000000000000000000000000000003 sha256 : 0 : 0000000000000000000000000000000000000000000000000000000000000003 ``` # OPTIONS * **-o**, **\--output**=_FILE_: The output file to write the PCR values in binary format, optional. [PCR output file format specifiers](common/pcrs_format.md) Default is 'values'. [common options](common/options.md) [common tcti options](common/tcti.md) [PCR bank specifiers](common/pcr.md) [supported hash algorithms](common/hash.md) [algorithm specifiers](common/alg.md) # EXAMPLES ## Display all PCR values ```bash tpm2_pcrread ``` ## Display the PCR values with a specified bank ```bash tpm2_pcrread sha1 ``` ## Display the PCR values with specified banks and store in a file ```bash tpm2_pcrread -o pcrs sha1:16,17,18+sha256:16,17,18 ``` ## Display the supported PCR bank algorithms and exit ```bash tpm2_pcrread ``` # NOTES The maximum number of PCR that can be dumped at once is associated with the maximum length of a bank. On most TPMs, it means that this tool can dump up to 24 PCRs at once. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_pcrreset.1.md000066400000000000000000000023441412464516500174400ustar00rootroot00000000000000% tpm2_pcrreset(1) tpm2-tools | General Commands Manual # NAME **tpm2_pcrreset**(1) - Reset one or more PCR banks # SYNOPSIS **tpm2_pcrreset** [*OPTIONS*] _PCR\_INDEX_ ... # DESCRIPTION **tpm2_pcrreset**(1) - Reset PCR value in all banks for specified index. More than one PCR index can be specified. The reset value is manufacturer-dependent and is either sequence of 00 or FF on the length of the hash algorithm for each supported bank. _PCR\_INDEX_ is a space separated list of PCR indexes to be reset when issuing the command. # OPTIONS This tool accepts no tool specific options. [common options](common/options.md) [common tcti options](common/tcti.md) # EXAMPLES ## Reset a single PCR ```bash tpm2_pcrreset 23 ``` ## Reset multiple PCRs ```bash tpm2_pcrreset 16 23 ``` # NOTES On operating system's locality (generally locality 0), only PCR 23 can be reset. PCR-16 can also be reset on this locality, depending on TPM manufacturers which could define this PCR as resettable. PCR 0 to 15 are not resettable (being part of SRTM). PCR 16 to 22 are mostly reserved for DRTM or dedicated to specific localities and might not be resettable depending on current TPM locality. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyauthorize.1.md000066400000000000000000000106141412464516500210420ustar00rootroot00000000000000% tpm2_policyauthorize(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyauthorize**(1) - Allows for mutable policies by tethering to a signing authority. # SYNOPSIS **tpm2_policyauthorize** [*OPTIONS*] # DESCRIPTION **tpm2_policyauthorize**(1) - This command allows for policies to change by associating the policy to a signing authority and allowing the policy contents to change. 1. If the input session is a trial session this tool generates a policy digest that associates a signing authority's public key name with the policy being authorized. 2. If the input session is real policy session **tpm2_policyauthorize**(1) looks for a verification ticket from the TPM to attest that the TPM has verified the signature on the policy digest before authorizing the policy in the policy digest. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-i**, **\--input**=_FILE_: The policy digest that has to be authorized. * **-q**, **\--qualification**=_FILE\_OR\_HEX_: The policy qualifier data signed in conjunction with the input policy digest. This is unique data that the signer can choose to include in the signature and can either be a path or hex string. * **-n**, **\--name**=_FILE_: File containing the name of the verifying public key. This ties the final policy digest with a signer. This can be retrieved with **tpm2_readpublic**(1) * **-t**, **\--ticket**=_FILE_: The ticket file to record the validation structure. This is generated with **tpm2_verifysignature**(1). ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Starts a *trial* session, builds a PCR policy. This PCR policy digest is then an input to the **tpm2_policyauthorize**(1) along with policy qualifier data and a signer public. The resultant policy digest is then used in creation of objects. Subsequently when the PCR change and so does the PCR policy digest, the actual policy digest from the **tpm2_policyauthorize**(1) used in creation of the object will not change. At runtime the new PCR policy needs to be satisfied along with verification of the signature on the PCR policy digest using **tpm2_policyauthorize**(1) ## Create a signing authority ```bash openssl genrsa -out signing_key_private.pem 2048 openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout tpm2_loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx -n signing_key.name ``` ## Create the authorize policy digest ```bash tpm2_startauthsession -S session.ctx tpm2_policyauthorize -S session.ctx -L authorized.policy -n signing_key.name tpm2_flushcontext session.ctx ``` ## Create a policy to be authorized like a PCR policy ```bash tpm2_pcrread -opcr0.sha256 sha256:0 tpm2_startauthsession -S session.ctx tpm2_policypcr -S session.ctx -l sha256:0 -f pcr0.sha256 -L pcr.policy_desired tpm2_flushcontext session.ctx ``` ## Sign the policy ```bash openssl dgst -sha256 -sign signing_key_private.pem -out pcr.signature pcr.policy_desired ``` ## Create a TPM object like a sealing object with the authorized policy based authentication ```bash tpm2_createprimary -C o -g sha256 -G rsa -c prim.ctx tpm2_create -g sha256 -u sealing_pubkey.pub -r sealing_prikey.pub -i- -C prim.ctx -L authorized.policy <<< "secret to seal" ``` ## Verify the desired policy digest comes from the signing authority, read the actual value of PCR and check that read policy and desired policy are equal. ```bash tpm2_verifysignature -c signing_key.ctx -g sha256 -m pcr.policy_desired -s pcr.signature -t verification.tkt -f rsassa tpm2_startauthsession \--policy-session -S session.ctx tpm2_policypcr -S session.ctx -l sha256:0 -L pcr.policy_read tpm2_policyauthorize -S session.ctx -L authorized.policy -i pcr.policy_desired -n signing_key.name -t verification.tkt tpm2_load -C prim.ctx -u sealing_pubkey.pub -r sealing_prikey.pub -c sealing_key.ctx unsealed=$(tpm2_unseal -p"session:session.ctx" -c sealing_key.ctx) echo $unsealed tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyauthorizenv.1.md000066400000000000000000000071611412464516500214110ustar00rootroot00000000000000% tpm2_policyauthorizenv(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyauthorizenv**(1) - Allows for mutable policies by referencing to a policy from an NV index. # SYNOPSIS **tpm2_policyauthorizenv** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policyauthorizenv**(1) - This command allows for policies to change by referencing the authorization policy written to an NV index. The NV index containing the authorization policy should remain readable even for trial session. The index can be specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX". # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Create a policypassword and write the policy digest to an NV Index. Build a policyauthorizenv policy referencing the NV index in a *trial* session. The resultant policy digest is then used in creation of objects. In a policy authorization session, first satisfy the policy written to the NV index. Then run the policyauthorizenv which satisfies the authorization for the object. ## Define the test NV Index to store the auth policy ```bash nv_test_index=0x01500001 tpm2_nvdefine -C o -p nvpass $nv_test_index -a "authread|authwrite" -s 34 ``` ## Define the auth policy ```bash tpm2_startauthsession -S session.ctx tpm2_policypassword -S session.ctx -L policy.pass tpm2_flushcontext session.ctx ``` ## Write the auth policy to the NV Index ```bash echo "000b" | xxd -p -r | cat - policy.pass | \ tpm2_nvwrite -C $nv_test_index -P nvpass $nv_test_index -i- ``` ## Define the policyauthorizenv ```bash tpm2_startauthsession -S session.ctx tpm2_policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass \ -L policyauthorizenv.1500001 $nv_test_index tpm2_flushcontext session.ctx ``` ## Create and load a sealing object with auth policy = policyauthorizenv ```bash tpm2_createprimary -C o -c prim.ctx echo "secretdata" | \ tpm2_create -C prim.ctx -u key.pub -r key.priv \ -a "fixedtpm|fixedparent|adminwithpolicy" -L policyauthorizenv.1500001 -i- tpm2_load -C prim.ctx -u key.pub -r key.priv -c key.ctx ``` ## Satisfy the auth policy stored in the NV Index and thus policyauthorizenv ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policypassword -S session.ctx tpm2_policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass $nv_test_index tpm2_unseal -c key.ctx -p session:session.ctx tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyauthvalue.1.md000066400000000000000000000045011412464516500210240ustar00rootroot00000000000000% tpm2_policyauthvalue(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyauthvalue**(1) - Enables binding a policy to the authorization value of the authorized TPM object. # SYNOPSIS **tpm2_policyauthvalue** [*OPTIONS*] # DESCRIPTION **tpm2_policyauthvalue**(1) - Enables a policy that requires the object's authentication passphrase be provided. This is equivalent to authenticating using the object passphrase in plaintext or HMAC. It enforces it as a policy. It provides a mechanism to allow for password authentication when an object only allows policy based authorization, ie object attribute "userwithauth" is 0. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES We want to authenticate using the TPM objects plaintext authentication value. While we could authenticate with an ephemeral password session, in this example we will authenticate with the plaintext passphrase in a policy session instead using the **tpm2_policyauthvalue**(1) tool. ## Create the password policy ```bash tpm2_startauthsession -S session.dat tpm2_policyauthvalue -S session.dat -L policy.dat tpm2_flushcontext session.dat ``` ## Create the object with a passphrase and the password policy ```bash tpm2_createprimary -C o -c prim.ctx tpm2_create -g sha256 -G aes -u key.pub -r key.priv -C prim.ctx -L policy.dat \ -p testpswd ``` ## Authenticate with plaintext passphrase input ```bash tpm2_load -C prim.ctx -u key.pub -r key.priv -n key.name -c key.ctx echo "plaintext" > plain.txt tpm2_encryptdecrypt -c key.ctx -o encrypt.out plain.txt -p testpswd ``` ## Authenticate with password and the policy ```bash tpm2_startauthsession --policy-session -S session.dat tpm2_policyauthvalue -S session.dat tpm2_encryptdecrypt -c key.ctx -o encrypt.out -p session:session.dat+testpswd \ plain.txt tpm2_flushcontext session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policycommandcode.1.md000066400000000000000000000150071412464516500213020ustar00rootroot00000000000000% tpm2_policycommandcode(1) tpm2-tools | General Commands Manual # NAME **tpm2_policycommandcode**(1) - Restrict TPM object authorization to specific TPM commands. # SYNOPSIS **tpm2_policycommandcode** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policycommandcode**(1) - Restricts TPM object authorization to specific TPM commands. Useful when you want to allow only specific commands to interact with the TPM object. As an argument it takes the command as an integer or friendly string value. Friendly string to COMMAND CODE mapping can be found in section *COMMAND CODE MAPPINGS*. # OPTIONS * **-S**, **\--session**=_FILE_: A session file from **tpm2_startauthsession**(1)'s **-S** option. * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **ARGUMENT** the command line argument specifies TPM2 command code. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # COMMAND CODE MAPPINGS The friendly strings below can be used en lieu of the raw integer values. -TPM2\_CC\_AC\_GetCapability: 0x194 -TPM2\_CC\_AC\_Send: 0x195 -TPM2\_CC\_ActivateCredential: 0x147 -TPM2\_CC\_Certify: 0x148 -TPM2\_CC\_CertifyCreation: 0x14a -TPM2\_CC\_ChangeEPS: 0x124 -TPM2\_CC\_ChangePPS: 0x125 -TPM2\_CC\_Clear: 0x126 -TPM2\_CC\_ClearControl: 0x127 -TPM2\_CC\_ClockRateAdjust: 0x130 -TPM2\_CC\_ClockSet: 0x128 -TPM2\_CC\_Commit: 0x18b -TPM2\_CC\_ContextLoad: 0x161 -TPM2\_CC\_ContextSave: 0x162 -TPM2\_CC\_Create: 0x153 -TPM2\_CC\_CreateLoaded: 0x191 -TPM2\_CC\_CreatePrimary: 0x131 -TPM2\_CC\_DictionaryAttackLockReset: 0x139 -TPM2\_CC\_DictionaryAttackParameters: 0x13a -TPM2\_CC\_Duplicate: 0x14b -TPM2\_CC\_ECC\_Parameters: 0x178 -TPM2\_CC\_ECDH\_KeyGen: 0x163 -TPM2\_CC\_ECDH\_ZGen: 0x154 -TPM2\_CC\_EC\_Ephemeral: 0x18e -TPM2\_CC\_EncryptDecrypt: 0x164 -TPM2\_CC\_EncryptDecrypt2: 0x193 -TPM2\_CC\_EventSequenceComplete: 0x185 -TPM2\_CC\_EvictControl: 0x120 -TPM2\_CC\_FieldUpgradeData: 0x141 -TPM2\_CC\_FieldUpgradeStart: 0x12f -TPM2\_CC\_FirmwareRead: 0x179 -TPM2\_CC\_FlushContext: 0x165 -TPM2\_CC\_GetCapability: 0x17a -TPM2\_CC\_GetCommandAuditDigest: 0x133 -TPM2\_CC\_GetRandom: 0x17b -TPM2\_CC\_GetSessionAuditDigest: 0x14d -TPM2\_CC\_GetTestResult: 0x17c -TPM2\_CC\_GetTime: 0x14c -TPM2\_CC\_Hash: 0x17d -TPM2\_CC\_HashSequenceStart: 0x186 -TPM2\_CC\_HierarchyChangeAuth: 0x129 -TPM2\_CC\_HierarchyControl: 0x121 -TPM2\_CC\_HMAC: 0x155 -TPM2\_CC\_HMAC\_Start: 0x15b -TPM2\_CC\_Import: 0x156 -TPM2\_CC\_IncrementalSelfTest: 0x142 -TPM2\_CC\_Load: 0x157 -TPM2\_CC\_LoadExternal: 0x167 -TPM2\_CC\_MakeCredential: 0x168 -TPM2\_CC\_NV\_Certify: 0x184 -TPM2\_CC\_NV\_ChangeAuth: 0x13b -TPM2\_CC\_NV\_DefineSpace: 0x12a -TPM2\_CC\_NV\_Extend: 0x136 -TPM2\_CC\_NV\_GlobalWriteLock: 0x132 -TPM2\_CC\_NV\_Increment: 0x134 -TPM2\_CC\_NV\_Read: 0x14e -TPM2\_CC\_NV\_ReadLock: 0x14f -TPM2\_CC\_NV\_ReadPublic: 0x169 -TPM2\_CC\_NV\_SetBits: 0x135 -TPM2\_CC\_NV\_UndefineSpace: 0x122 -TPM2\_CC\_NV\_UndefineSpaceSpecial: 0x11f -TPM2\_CC\_NV\_Write: 0x137 -TPM2\_CC\_NV\_WriteLock: 0x138 -TPM2\_CC\_ObjectChangeAuth: 0x150 -TPM2\_CC\_PCR\_Allocate: 0x12b -TPM2\_CC\_PCR\_Event: 0x13c -TPM2\_CC\_PCR\_Extend: 0x182 -TPM2\_CC\_PCR\_Read: 0x17e -TPM2\_CC\_PCR\_Reset: 0x13d -TPM2\_CC\_PCR\_SetAuthPolicy: 0x12c -TPM2\_CC\_PCR\_SetAuthValue: 0x183 -TPM2\_CC\_Policy\_AC\_SendSelect: 0x196 -TPM2\_CC\_PolicyAuthorize: 0x16a -TPM2\_CC\_PolicyAuthorizeNV: 0x192 -TPM2\_CC\_PolicyAuthValue: 0x16b -TPM2\_CC\_PolicyCommandCode: 0x16c -TPM2\_CC\_PolicyCounterTimer: 0x16d -TPM2\_CC\_PolicyCpHash: 0x16e -TPM2\_CC\_PolicyDuplicationSelect: 0x188 -TPM2\_CC\_PolicyGetDigest: 0x189 -TPM2\_CC\_PolicyLocality: 0x16f -TPM2\_CC\_PolicyNameHash: 0x170 -TPM2\_CC\_PolicyNV: 0x149 -TPM2\_CC\_PolicyNvWritten: 0x18f -TPM2\_CC\_PolicyOR: 0x171 -TPM2\_CC\_PolicyPassword: 0x18c -TPM2\_CC\_PolicyPCR: 0x17f -TPM2\_CC\_PolicyPhysicalPresence: 0x187 -TPM2\_CC\_PolicyRestart: 0x180 -TPM2\_CC\_PolicySecret: 0x151 -TPM2\_CC\_PolicySigned: 0x160 -TPM2\_CC\_PolicyTemplate: 0x190 -TPM2\_CC\_PolicyTicket: 0x172 -TPM2\_CC\_PP\_Commands: 0x12d -TPM2\_CC\_Quote: 0x158 -TPM2\_CC\_ReadClock: 0x181 -TPM2\_CC\_ReadPublic: 0x173 -TPM2\_CC\_Rewrap: 0x152 -TPM2\_CC\_RSA\_Decrypt: 0x159 -TPM2\_CC\_RSA\_Encrypt: 0x174 -TPM2\_CC\_SelfTest: 0x143 -TPM2\_CC\_SequenceComplete: 0x13e -TPM2\_CC\_SequenceUpdate: 0x15c -TPM2\_CC\_SetAlgorithmSet: 0x13f -TPM2\_CC\_SetCommandCodeAuditStatus: 0x140 -TPM2\_CC\_SetPrimaryPolicy: 0x12e -TPM2\_CC\_Shutdown: 0x145 -TPM2\_CC\_Sign: 0x15d -TPM2\_CC\_StartAuthSession: 0x176 -TPM2\_CC\_Startup: 0x144 -TPM2\_CC\_StirRandom: 0x146 -TPM2\_CC\_TestParms: 0x18a -TPM2\_CC\_Unseal: 0x15e -TPM2\_CC\_Vendor\_TCG\_Test: 0x20000000 -TPM2\_CC\_VerifySignature: 0x177 -TPM2\_CC\_ZGen\_2Phase: 0x18d # EXAMPLES Start a *policy* session and extend it with a specific command like unseal. Attempts to perform other operations would fail. ## Create an unseal-only policy ```bash tpm2_startauthsession -S session.dat tpm2_policycommandcode -S session.dat -L policy.dat TPM2_CC_Unseal tpm2_flushcontext session.dat ``` ## Create the object with unseal-only auth policy ```bash tpm2_createprimary -C o -c prim.ctx tpm2_create -C prim.ctx -u sealkey.pub -r sealkey.priv -L policy.dat \ -i- <<< "SEALED-SECRET" ``` ## Try unseal operation ```bash tpm2_load -C prim.ctx -u sealkey.pub -r sealkey.priv -n sealkey.name \ -c sealkey.ctx tpm2_startauthsession --policy-session -S session.dat tpm2_policycommandcode -S session.dat -L policy.dat TPM2_CC_Unseal tpm2_unseal -p session:session.dat -c sealkey.ctx SEALED-SECRET tpm2_flushcontext session.dat ``` ## Try any other operation ```bash echo "Encrypt Me" > plain.txt tpm2_encryptdecrypt plain.txt -o enc.txt -c sealkey.ctx plain.txt ERROR: Esys_EncryptDecrypt2(0x12F) - tpm:error(2.0): authValue or authPolicy is not available for selected entity ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policycountertimer.1.md000066400000000000000000000070471412464516500215560ustar00rootroot00000000000000% tpm2_policycountertimer(1) tpm2-tools | General Commands Manual # NAME **tpm2_policycountertimer**(1) - Enables policy authorization by evaluating the comparison operation on the TPM parameters time, clock, reset count, restart count and TPM clock safe flag. # SYNOPSIS **tpm2_policycountertimer** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policycountertimer**(1) - Enables policy authorization by evaluating the comparison operation on the TPM parameters time, clock, reset count, restart count and TPM clock safe flag. If time/clock, it is input as milliseconds value. The parameter and the value is given as a command line argument as below: ``` tpm2_policycountertimer -S session.ctx safe tpm2_policycountertimer -S session.ctx clock= tpm2_policycountertimer -S session.ctx time= tpm2_policycountertimer -S session.ctx resets= tpm2_policycountertimer -S session.ctx restarts= ``` By default comparison tests for equality and also by default it tests for time. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession** or saved off of a previous tool run. * **--eq** if value of current time in the TPM = value of specified input time. * **--neq** if value of current time in the TPM != value of specified input time. * **--sgt** if signed value of current time in the TPM > signed value of specified input time. * **--ugt** if unsigned value of current time in the TPM > unsigned value of specified input time. * **--slt** if signed value of current time in the TPM < signed value of specified input time. * **--ult** if unsigned value of current time in the TPM < unsigned value of specified input time. * **--sge** if signed value of current time in the TPM >= signed value of specified input time. * **--uge** if unsigned value of current time in the TPM >= unsigned value of specified input time. * **--sle** if signed value of current time in the TPM <= unsigned value of specified input time. * **--ule** if unsigned value of current time in the TPM <= unsigned value of specified input time. * **--bs** if all bits set in value of current time in the TPM are set in value of specified input time. * **--bc** if all bits set in value of current time in the TPM are clear in value of specified input time. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Create a sealing object with an authorization policy that evaluates only for first minute of TPM restart. ## Create the policy and the sealing object ```bash tpm2_startauthsession -S session.ctx tpm2_policycountertimer -S session.ctx -L policy.countertimer --ult 60000 tpm2_flushcontext session.ctx tpm2_createprimary -C o -c prim.ctx -Q echo "SUPERSECRET" | \ tpm2_create -Q -u key.pub -r key.priv -i- -C prim.ctx \ -L policy.countertimer -a "fixedtpm|fixedparent" -c key.ctx ``` ## Unsealing should work in the first minute after TPM restart ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policycountertimer -S session.ctx --ult 60000 tpm2_unseal -c key.ctx -p session:session.ctx tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policycphash.1.md000066400000000000000000000050641412464516500203010ustar00rootroot00000000000000% tpm2_policycphash(1) tpm2-tools | General Commands Manual # NAME **tpm2_policycphash**(1) - Couples a policy with command parameters of the command. # SYNOPSIS **tpm2_policycphash** [*OPTIONS*] # DESCRIPTION **tpm2_policycphash**(1) - Couples a policy with command parameters of the command. This is a deferred assertion where the hash of the command parameters in a TPM command is checked against the one specified in the policy. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **\--cphash-input**=_FILE_: The file containing the command parameter hash of the command. * **\--cphash**=_FILE_: **DEPRECATED**, use **--cphash-input** instead. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Restrict the value that can be set through tpm2_nvsetbits. ## Define NV index object with authorized policy ```bash openssl genrsa -out signing_key_private.pem 2048 openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout tpm2_loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx \ -n signing_key.name tpm2_startauthsession -S session.ctx -g sha256 tpm2_policyauthorize -S session.ctx -L authorized.policy -n signing_key.name tpm2_flushcontext session.ctx tpm2_nvdefine 1 -a "policywrite|authwrite|ownerread|nt=bits" -L authorized.policy ``` ## Create policycphash ```bash tpm2_nvsetbits 1 -i 1 --cphash cp.hash tpm2_startauthsession -S session.ctx -g sha256 tpm2_policycphash -S session.ctx -L policy.cphash --cphash cp.hash tpm2_flushcontext session.ctx ``` ## Sign and verify policycphash ```bash openssl dgst -sha256 -sign signing_key_private.pem \ -out policycphash.signature policy.cphash tpm2_verifysignature -c signing_key.ctx -g sha256 -m policy.cphash \ -s policycphash.signature -t verification.tkt -f rsassa ``` ## Satisfy policycphash and execute nvsetbits ```bash tpm2_startauthsession -S session.ctx --policy-session -g sha256 tpm2_policycphash -S session.ctx --cphash cp.hash tpm2_policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt tpm2_nvsetbits 1 -i 1 -P "session:session.ctx" tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyduplicationselect.1.md000066400000000000000000000050231412464516500225410ustar00rootroot00000000000000% tpm2_policyduplicationselect(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyduplicationselect**(1) - Restricts duplication to a specific new parent. # SYNOPSIS **tpm2_policyduplicationselect** [*OPTIONS*] # DESCRIPTION **tpm2_policyduplicationselect**(1) - Restricts duplication to a specific new parent. # OPTIONS * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-n**, **\--object-name**=_FILE_: Input name file of the object to be duplicated. * **-N**, **\--parent-name**=_FILE_: Input name file of the new parent. * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **\--include-object**: If exists, the object name will be included in the value in policy digest. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Setup a duplication role policy to restricted new parent ### Create source parent and destination(or new) parent ```bash tpm2_createprimary -C n -g sha256 -G rsa -c dst_n.ctx -Q tpm2_createprimary -C o -g sha256 -G rsa -c src_o.ctx -Q ``` ### Create the restricted parent policy ```bash tpm2_readpublic -c dst_n.ctx -n dst_n.name -Q tpm2_startauthsession -S session.ctx tpm2_policyduplicationselect -S session.ctx -N dst_n.name \ -L policydupselect.dat -Q tpm2_flushcontext session.ctx rm session.ctx ``` ### Create the object to be duplicated using the policy ```bash tpm2_create -C src_o.ctx -g sha256 -G rsa -r dupkey.priv -u dupkey.pub \ -L policydupselect.dat -a "sensitivedataorigin|sign|decrypt" -c dupkey.ctx -Q tpm2_readpublic -c dupkey.ctx -n dupkey.name -Q ``` ### Satisfy the policy and duplicate the object ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policyduplicationselect -S session.ctx -N dst_n.name -n dupkey.name -Q tpm2_duplicate -C dst_n.ctx -c dupkey.ctx -G null -p session:session.ctx \ -r new_dupkey.priv -s dupseed.dat tpm2_flushcontext session.ctx rm session.ctx ``` # NOTES * This command usually cooperates with **tpm2_duplicate**(1), so referring to the man page of **tpm2_duplicate**(1) is recommended. * This command will set the policy session's command code to **TPM_CC_Duplicate** which enables duplication role of the policy. [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policylocality.1.md000066400000000000000000000055471412464516500206610ustar00rootroot00000000000000% tpm2_policylocality(1) tpm2-tools | General Commands Manual # NAME **tpm2_policylocality**(1) - Restrict TPM object authorization to specific localities. # SYNOPSIS **tpm2_policylocality** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policylocality**(1) - Restricts TPM object authorization to specific TPM locality. Useful when you want to allow only specific locality with the TPM object. A locality indicates the source of the command, for example it could be from the application layer or the driver layer, each would have it's own locality integer. Localities are hints to the TPM and are enforced by the software communicating to the TPM. Thus they are **not trusted** inputs on their own and are implemented in platform specific ways. As an argument it takes the _LOCALITY_ as an integer or friendly name. Localities are fixed to a byte in size and have two representations, locality and extended locality. Localities 0 through 4 are the normal locality representation and are represented as set bit indexes. Thus locality 0 is indicated by `1<<0` and locality 4 is indicated by `1<<4`. Rather then using raw numbers, these localities can also be specified by the friendly names of: - zero: locality 0 or `1<<0` - one: locality 1 or `1<<1` - two: locality 2 or `1<<2` - three: locality 3 or `1<<3` - four: locality 4 or `1<<4` Anything from the range 32 - 255 are extended localities. # OPTIONS * **-S**, **\--session**=_FILE_: A session file from **tpm2_startauthsession**(1)'s **-S** option. * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **ARGUMENT** the command line argument specifies the locality number. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Start a *policy* session and extend it with a specific locality number (like 3). Attempts to perform other operations would fail. ## Create an policy restricted by locality 3 ```bash tpm2_startauthsession -S session.dat tpm2_policylocality -S session.dat -L policy.dat three tpm2_flushcontext session.dat ``` ## Create the object with auth policy ```bash tpm2_createprimary -C o -c prim.ctx tpm2_create -C prim.ctx -u sealkey.pub -r sealkey.priv -L policy.dat \ -i- <<< "SEALED-SECRET" ``` ## Try unseal operation ```bash tpm2_load -C prim.ctx -u sealkey.pub -r sealkey.priv -n sealkey.name \ -c sealkey.ctx tpm2_startauthsession \--policy-session -S session.dat tpm2_policylocality -S session.dat -L policy.dat three # Change to locality 3, Note: this operation varies on different platforms tpm2_unseal -p session:session.dat -c sealkey.ctx tpm2_flushcontext session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policynamehash.1.md000066400000000000000000000067741412464516500206300ustar00rootroot00000000000000% tpm2_policynamehash(1) tpm2-tools | General Commands Manual # NAME **tpm2_policynamehash**(1) - Couples a policy with names of specific objects. # SYNOPSIS **tpm2_policynamehash** [*OPTIONS*] # DESCRIPTION **tpm2_policynamehash**(1) - Couples a policy with names of specific objects. This is a deferred assertion where the hash of the names of all object handles in a TPM command is checked against the one specified in the policy. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-n**, **\--name**=_FILE_: The file containing the name hash of the referenced objects. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Restrict key duplication to specific new parent and specific duplicable key. # Generate a duplicable object ```bash openssl genrsa -out signing_key_private.pem 2048 openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout tpm2_loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx \ -n signing_key.name tpm2_startauthsession -S session.ctx -g sha256 tpm2_policyauthorize -S session.ctx -L authorized.policy -n signing_key.name tpm2_policycommandcode -S session.ctx -L policy.dat TPM2_CC_Duplicate tpm2_flushcontext session.ctx tpm2_createprimary -C o -g sha256 -G rsa -c primary.ctx -Q ## The duplicable key tpm2_create -Q -C primary.ctx -g sha256 -G rsa -r key.prv -u key.pub \ -L policy.dat -a "sensitivedataorigin|sign|decrypt" tpm2_load -Q -C primary.ctx -r key.prv -u key.pub -c key.ctx ``` # Create the new parent ```bash tpm2_create -Q -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub \ -a "decrypt|fixedparent|fixedtpm|restricted|sensitivedataorigin" tpm2_loadexternal -Q -C o -u new_parent.pub -c new_parent.ctx ``` # Modify the duplicable key policy to namehash policy to restrict parent and key ```bash tpm2_readpublic -Q -c new_parent.ctx -n new_parent.name tpm2_readpublic -Q -c key.ctx -n key.name cat key.name new_parent.name | openssl dgst -sha256 -binary > name.hash tpm2_startauthsession -S session.ctx -g sha256 tpm2_policynamehash -L policy.namehash -S session.ctx -n name.hash tpm2_flushcontext session.ctx openssl dgst -sha256 -sign signing_key_private.pem \ -out policynamehash.signature policy.namehash tpm2_startauthsession -S session.ctx -g sha256 tpm2_policyauthorize -S session.ctx -L authorized.policy -i policy.namehash \ -n signing_key.name tpm2_policycommandcode -S session.ctx -L policy.dat TPM2_CC_Duplicate tpm2_flushcontext session.ctx ``` # Satisfy the policy and attempt key duplication ```bash tpm2_verifysignature -c signing_key.ctx -g sha256 -m policy.namehash \ -s policynamehash.signature -t verification.tkt -f rsassa tpm2_startauthsession -S session.ctx --policy-session -g sha256 tpm2_policynamehash -S session.ctx -n name.hash tpm2_policyauthorize -S session.ctx -i policy.namehash -n signing_key.name \ -t verification.tkt tpm2_policycommandcode -S session.ctx TPM2_CC_Duplicate tpm2_duplicate -C new_parent.ctx -c key.ctx -G null -p "session:session.ctx" \ -r dupprv.bin -s dupseed.dat tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policynv.1.md000066400000000000000000000105561412464516500174600ustar00rootroot00000000000000% tpm2_policynv(1) tpm2-tools | General Commands Manual # NAME **tpm2_policynv**(1) - Evaluates policy authorization by comparing a specified value against the contents in the specified NV Index. # SYNOPSIS **tpm2_policynv** [*OPTIONS*] [*ARGUMENT*] [*ARGUMENT*] # DESCRIPTION **tpm2_policynv**(1) - This command evaluates policy authorization by comparing the contents written to an NV index against the one specified in the tool options. The tool takes two arguments - (1) The NV index specified as raw handle or an offset value to the nv handle range "TPM2_HR_NV_INDEX" and (2) Comparison operator for magnitude comparison and or bit test operations. In the specification the NV index holding the data is called operandA and the data that the user specifies to compare is called operandB. The comparison operator can be specified as follows: * "eq" if operandA = operandB * "neq" if operandA != operandB * "sgt" if signed operandA > signed operandB * "ugt" if unsigned operandA > unsigned operandB * "slt" if signed operandA < signed operandB * "ult" if unsigned operandA < unsigned operandB * "sge" if signed operandA >= signed operandB * "uge" if unsigned operandA >= unsigned operandB * "sle" if signed operandA <= unsigned operandB * "ule" if unsigned operandA <= unsigned operandB * "bs" if all bits set in operandA are set in operandB * "bc" if all bits set in operandA are clear in operandB # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy used to authorize. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **``** where a hierarchy handle or nv-index may be used. When **-C** isn't explicitly passed the index handle will be used to authorize against the index. The index auth value is set via the **-p** option to **tpm2_nvdefine**(1). * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession** or saved off of a previous tool run. * **\--offset**=_NATURAL_NUMBER_: The offset within the NV index to start comparing at. The size of the data starting at offset and ending at size of NV index shall not exceed the size of the operand specified in the options. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **-i**, **\--input**=_FILE_: Specifies the input file with data to compare to NV Index contents. In the standard specification, this is termed as operand or operandB more specifically . It can be specified as a file input or stdin if option value is a "-". ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Test if NV index content value is equal to an input number. To do this we first create an NV index of size 1 byte and write a value. Eg. 0xAA. Next we attempt to create a policy that becomes valid if the equality comparison operation of the NV index content against the one specified in the tool options. ## Define the test NV Index and write the value 0xAA to it ```bash nv_test_index=0x01500001 tpm2_nvdefine -C o -p nvpass $nv_test_index -a "authread|authwrite" -s 1 echo "aa" | xxd -r -p | tpm2_nvwrite -P nvpass -i- $nv_test_index ``` ## Attempt defining policynv with wrong comparison value specified in options. ```bash tpm2_startauthsession -S session.ctx --policy-session ### This should fail echo 0xBB | tpm2_policynv -S session.ctx -L policy.nv -i- 0x1500001 eq -P nvpass tpm2_flushcontext session.ctx ``` ## Attempt defining policynv with right comparison value specified in options. ```bash tpm2_startauthsession -S session.ctx --policy-session ### This should pass echo 0xAA | tpm2_policynv -S session.ctx -L policy.nv -i- 0x1500001 eq -P nvpass tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policynvwritten.1.md000066400000000000000000000035271412464516500210750ustar00rootroot00000000000000% tpm2_policynvwritten(1) tpm2-tools | General Commands Manual # NAME **tpm2_policynvwritten**(1) - Restrict TPM object authorization to the written state of an NV index. # SYNOPSIS **tpm2_policynvwritten** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policynvwritten**(1) - Restricts TPM object authorization to the written state of an NV index. Useful when creating write once NV indexes. As an [*ARGUMENT*] it takes the expected written state of the NV index. It can be specified as s|c|0|1. # OPTIONS * **-S**, **\--session**=_FILE_: A session file from **tpm2_startauthsession**(1)'s **-S** option. * **-L**, **\--policy**=_FILE_: File to save the policy digest. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Create a write once NV index. To do this the NV index is defined with a write policy that is valid only if the NV index attribute "TPMA_NV_WRITTEN" was never set. ## Define the NV index write policy ```bash tpm2_startauthsession -S session.dat tpm2_policycommandcode -S session.dat TPM2_CC_NV_Write tpm2_policynvwritten -S session.dat -L nvwrite.policy c tpm2_flushcontext session.dat ``` ## Define the NV index with the policy ```bash tpm2_nvdefine -s 1 -a "authread|policywrite" -p nvrdpass -L nvwrite.policy ``` ## Write the NV index by satisfying the policy ```bash tpm2_startauthsession -S session.dat --policy-session tpm2_policycommandcode -S session.dat TPM2_CC_NV_Write tpm2_policynvwritten -S session.dat c echo 0xAA | xxd -r -p | tpm2_nvwrite 0x01000000 -i- -P session:session.dat tpm2_flushcontext session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyor.1.md000066400000000000000000000064771412464516500174640ustar00rootroot00000000000000% tpm2_policyor(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyor**(1) - logically OR's two policies together. # SYNOPSIS **tpm2_policyor** [*OPTIONS*] # DESCRIPTION **tpm2_policyor**(1) - Generates a policy_or event with the TPM. It expects a session to be already established via **tpm2_startauthsession**(1). If the input session is a trial session this tool generates a policy digest that compounds two or more input policy digests such that the resulting policy digest requires at least one of the policy events being true. If the input session is real policy session **tpm2_policyor**(1) authenticates the object successfully if at least one of the policy events are true. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **ARGUMENT** the command line argument specifies the list of files for the policy digests that has to be compounded resulting in individual policies being added to final policy digest that can authenticate the object. The list begins with the policy digest hash alg. Example sha256:policy1,policy2 * **-l**, **\--policy-list**=_POLICY\_FILE_\_LIST: This option is retained for backwards compatibility. Use the argument method instead. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Create an authorization policy for a sealing object that compounds a pcr policy and a policypassword in an OR fashion and show satisfying either policies could unseal the secret. ## Create policypcr as first truth value for compounding the policies ```bash tpm2_startauthsession -S session.ctx tpm2_policypcr -S session.ctx -L policy.pcr -l sha256:0,1,2,3 tpm2_flushcontext session.ctx ``` ## Create policypassword as second truth value for compounding the policies ```bash tpm2_startauthsession -S session.ctx tpm2_policypassword -S session.ctx -L policy.pass tpm2_flushcontext session.ctx ``` ## Compound the two policies in an OR fashion with tpm2_policyor command ```bash tpm2_startauthsession -S session.ctx tpm2_policyor -S session.ctx -L policy.or sha256:policy.pass,policy.pcr tpm2_flushcontext session.ctx ``` ## Create a sealing object and attach the auth policy from tpm2_policyor command ```bash tpm2_createprimary -c prim.ctx -Q echo "secret" | tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv \ -L policy.or -i- ``` ## Satisfy auth policy using password and unseal the secret ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policypassword -S session.ctx tpm2_policyor -S session.ctx sha256:policy.pass,policy.pcr tpm2_unseal -c key.ctx -p session:session.ctx tpm2_flushcontext session.ctx ``` ## Satisfy auth policy using pcr and unseal the secret ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policypcr -S session.ctx -l sha256:0,1,2,3 tpm2_policyor -S session.ctx sha256:policy.pass,policy.pcr tpm2_unseal -c key.ctx -p session:session.ctx tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policypassword.1.md000066400000000000000000000045241412464516500206750ustar00rootroot00000000000000% tpm2_policypassword(1) tpm2-tools | General Commands Manual # NAME **tpm2_policypassword**(1) - Enables binding a policy to the authorization value of the authorized TPM object. # SYNOPSIS **tpm2_policypassword** [*OPTIONS*] # DESCRIPTION **tpm2_policypassword**(1) - Enables a policy that requires the object's authentication passphrase be provided. This is equivalent to authenticating using the object passphrase in plaintext, only this enforces it as a policy. It provides a mechanism to allow for password authentication when an object only allows policy based authorization, ie object attribute "userwithauth" is 0. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES We want to authenticate using the TPM objects plaintext authentication value. While we could authenticate with an ephemeral password session, in this example we will authenticate with the plaintext passphrase in a policy session instead using the **tpm2_policypassword**(1) tool. ## Create the password policy ```bash tpm2_startauthsession -S session.dat tpm2_policypassword -S session.dat -L policy.dat tpm2_flushcontext session.dat ``` ## Create the object with a passphrase and the password policy ```bash tpm2_createprimary -C o -c prim.ctx tpm2_create -g sha256 -G aes -u key.pub -r key.priv -C prim.ctx -L policy.dat \ -p testpswd ``` ## Authenticate with plaintext passphrase input ```bash tpm2_load -C prim.ctx -u key.pub -r key.priv -n key.name -c key.ctx echo "plaintext" > plain.txt tpm2_encryptdecrypt -c key.ctx -o encrypt.out plain.txt -p testpswd plain.txt ``` ## Authenticate with password and the policy ```bash tpm2_startauthsession \--policy-session -S session.dat tpm2_policypassword -S session.dat -L policy.dat tpm2_encryptdecrypt -c key.ctx -o encrypt.out \ -p session:session.dat+testpswd plain.txt tpm2_flushcontext session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policypcr.1.md000066400000000000000000000060621412464516500176160ustar00rootroot00000000000000% tpm2_policypcr(1) tpm2-tools | General Commands Manual # NAME **tpm2_policypcr**(1) - Create a policy that includes specific PCR values. # SYNOPSIS **tpm2_policypcr** [*OPTIONS*] # DESCRIPTION **tpm2_policypcr**(1) - Generates a PCR policy event with the TPM. A PCR policy event creates a policy bound to specific PCR values and is useful within larger policies constructed using policyor and policyauthorize events. See **tpm2_policyor(1)** and **tpm2_policyauthorize(1)** respectively for their usages. The PCR data factored into the policy can be specified in one of 3 ways: 1. A file containing a concatenated list of PCR values as in the output from **tpm2_pcrread**. 2. Requiring the PCR values be read off the TPM by not specifying a PCR file input. 3. The digest of all the PCR values directly specified as an **argument**. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-f**, **\--pcr**=_FILE_: Optional Path or Name of the file containing expected PCR values for the specified index. Default is to read the current PCRs per the set list. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **ARGUMENT**: The calculated digest of all PCR values specified as a hex byte stream. Eg: `openssl dgst -sha256 -binary pcr.bin | xxd -p -c 32` ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [pcr bank specifiers](common/pcr.md) details the syntax for specifying pcr list _PCR_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Starts a *trial* session, builds a PCR policy and uses that policy in the creation of an object. Then, it uses a *policy* session to unseal some data stored in the object. ## Step 1: create a policy ```bash tpm2_createprimary -C e -g sha256 -G ecc -c primary.ctx tpm2_pcrread -o pcr.dat "sha1:0,1,2,3" tpm2_startauthsession -S session.dat tpm2_policypcr -S session.dat -l "sha1:0,1,2,3" -f pcr.dat -L policy.dat tpm2_flushcontext session.dat ``` # Step 2: create an object using that policy ```bash tpm2_create -Q -u key.pub -r key.priv -C primary.ctx -L policy.dat \ -i- <<< "12345678" tpm2_load -C primary.ctx -u key.pub -r key.priv -n unseal.key.name \ -c unseal.key.ctx ``` ## Step 3: Satisfy the policy ```bash tpm2_startauthsession --policy-session -S session.dat tpm2_policypcr -S session.dat -l "sha1:0,1,2,3" -f pcr.dat -L policy.dat ``` ## Step 4: Use the policy ```bash tpm2_unseal -psession:session.dat -c unseal.key.ctx 12345678 tpm2_flushcontext session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyrestart.1.md000066400000000000000000000041031412464516500205100ustar00rootroot00000000000000% tpm2_policyrestart(1) tpm2-tools | General Commands Manual # NAME **tpm2_policyrestart**(1) - Restart an existing session with the TPM. # SYNOPSIS **tpm2_policyrestart** [*OPTIONS*] # DESCRIPTION **tpm2_policyrestart**(1) - Restarts a session with the TPM back to it's initial state. This is useful when the TPM gives one a **TPM_RC_PCR_CHANGED** (`0x00000128`) error code when using a PCR policy session. This will be returned if a PCR state affecting policy is altered during the session. One could restart the session and try again, however, the PCR state would still need to satisfy the policy. # OPTIONS * **-S**, **\--session**=_FILE_: Optional, A session file from **tpm2_startauthsession**(1)'s **-S** option. This session is used in lieu of starting a session and using the PCR policy options. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Start a *policy* session and restart it, unsealing some data. ```bash # create a policy and bind it to an object tpm2_startauthsession -S session.dat tpm2_policypcr -S session.dat -l "sha1:0,1,2,3" -L policy.dat tpm2_createprimary -c primary.ctx tpm2_create -Cprimary.ctx -u key.pub -r key.priv -L policy.dat -i- <<< "secret" tpm2_load -C primary.ctx -c key.ctx -u key.pub -r key.priv tpm2_flushcontext session.dat # satisfy the policy and use the object tpm2_startauthsession --policy -S session.dat tpm2_policypcr -S session.dat -l "sha1:0,1,2,3" # PCR event occurs here causing unseal to fail tpm2_pcrevent 0 <<< "event data" tpm2_unseal -psession:session.dat -c key.ct ERROR: Esys_Unseal(0x128) - tpm:error(2.0): PCR have changed since checked # Clear the policy digest to initial state, note access to object no longer allowed by # policy so policyor would be useful here. tpm2_policyrestart -S session.dat ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policysecret.1.md000066400000000000000000000101031412464516500203060ustar00rootroot00000000000000% tpm2_policysecret(1) tpm2-tools | General Commands Manual # NAME **tpm2_policysecret**(1) - Couples the authorization of an object to that of an existing object. # SYNOPSIS **tpm2_policysecret** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_policysecret**(1) - Couples the authorization of an object to that of an existing object without requiring exposing the existing secret until time of object use. # OPTIONS * **-c**, **\--object-context**=_OBJECT_: A context object specifier of a transient/permanent/persistent object. Either a file path of a object context blob or a loaded/persistent/permanent handle id. See section "Context Object Format". As an argument, it takes the auth value of the associated TPM object, a single dash - can be used to read the auth value from stdin. The argument follows the "authorization formatting standards", see section "Authorization Formatting". * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-L**, **\--policy**=_FILE_: File to save the policy digest. * **-t**, **\--expiration**=_NATURAL_NUMBER_: Set the expiration time of the policy in seconds. In absence of nonceTPM the expiration time is the policy timeout value. If expiration value is 0 then the policy does not have a time limit on the authorization. * **\--ticket**=_FILE_: The ticket file to record the authorization ticket structure. * **\--timeout**=_FILE_: The file path to record the timeout structure returned. * **-x**, **\--nonce-tpm**: Enable the comparison of the current session's nonceTPM to ensure the validity of the policy authorization is limited to the current session. * **-q**, **\--qualification**=_FILE\_OR\_HEX\_STR_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can be either a hex string or path. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash to be used in an audit or a policycphash. * **ARGUMENT** the command line argument specifies the _AUTH_ to be set for the object specified with **-c**. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Associate auth value of a sealing object to the owner hierarchy password. * Start a trial auth session and run **tpm2_policysecret**(1) to create policy that can only be satisfied if owner hierarchy auth value is supplied. * Start a real policy session and provide the owner hierarchy auth value. * Provide the session input where in the policysecret for owner hierarchy auth was satisfied to the unseal tool. * If the policy was satisfied unsealing should succeed. ## Generate a policy that binds to the secret of the owner hiearchy ```bash tpm2_startauthsession -S session.ctx tpm2_policysecret -S session.ctx -c o -L secret.policy tpm2_flushcontext session.ctx ``` ## Create a TPM object using the policy ```bash tpm2_createprimary -Q -C o -g sha256 -G rsa -c prim.ctx tpm2_create -Q -g sha256 -u sealing_key.pub -r sealing_key.priv -i- \ -C prim.ctx -L secret.policy <<< "SEALED-SECRET" tpm2_load -C prim.ctx -u sealing_key.pub -r sealing_key.priv \ -c sealing_key.ctx ``` ## Satisfy the policy and unseal the secret ```bash tpm2_startauthsession --policy-session -S session.ctx tpm2_policysecret -S session.ctx -c o -L secret.policy tpm2_unseal -p "session:session.ctx" -c sealing_key.ctx SEALED-SECRET tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policysigned.1.md000066400000000000000000000101241412464516500202750ustar00rootroot00000000000000% tpm2_policysigned(1) tpm2-tools | General Commands Manual # NAME **tpm2_policysigned**(1) - Enables policy authorization by verifying signature of optional TPM2 parameters. The signature is generated by a signing authority. # SYNOPSIS **tpm2_policysigned** [*OPTIONS*] # DESCRIPTION **tpm2_policysigned**(1) - Enables policy authorization by verifying signature of optional TPM2 parameters. The signature is generated by a signing authority. The optional TPM2 parameters being cpHashA, nonceTPM, policyRef and expiration. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-c**, **\--key-context**=_OBJECT_: Context object for the key context used for the operation. Either a file or a handle number. See section "Context Object Format". * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the message. * **-s**, **\--signature**=_FILE_: The input signature file of the signature to be validated. * **-f**, **\--format**=_FORMAT_: Set the input signature file to a specified format. The default is the tpm2.0 TPMT_SIGNATURE data format, however different schemes can be selected if the data came from an external source like OpenSSL. The tool currently supports rsassa and ecdsa. * **-t**, **\--expiration**=_NATURAL_NUMBER_: Set the expiration time of the policy in seconds. In absence of nonceTPM the expiration time is the policy timeout value. If expiration is a negative value an authorization ticket is additionally returned. If expiration value is 0 then the policy does not have a time limit on the authorization. * **\--cphash-input**=_FILE_: The command parameter hash (cpHash), enforcing the TPM command to be authorized as well as its handle and parameter values. * **\--ticket**=_FILE_: The ticket file to record the authorization ticket structure. * **\--timeout**=_FILE_: The file path to record the timeout structure returned. * **-q**, **\--qualification**=_FILE\_OR\_HEX\_STR_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can be either a hex string or path. * **-x**, **\--nonce-tpm**: Enable the comparison of the current session's nonceTPM to ensure the validity of the policy authorization is limited to the current session. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Authorize a TPM operation on an object whose authorization is bound to specific signing authority. ## Create the signing authority ```bash openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem ``` ## Generate signature with nonceTPM, cpHashA, policyRef and expiration set to 0 ```bash echo "00 00 00 00" | xxd -r -p | \ openssl dgst -sha256 -sign private.pem -out signature.dat ``` ## Load the verification key and Create the policysigned policy ```bash tpm2_loadexternal -C o -G rsa -u public.pem -c signing_key.ctx tpm2_startauthsession -S session.ctx tpm2_policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -L policy.signed tpm2_flushcontext session.ctx ``` ## Create a sealing object to use the policysigned ```bash echo "plaintext" > secret.data tpm2_createprimary -C o -c prim.ctx tpm2_create -u key.pub -r sealing_key.priv -c sealing_key.ctx -C prim.ctx \ -i secret.data -L policy.signed ``` ## Satisfy the policy and unseal secret ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -L policy.signed tpm2_unseal -p session:session.ctx -c sealing_key.ctx tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policytemplate.1.md000066400000000000000000000034061412464516500206440ustar00rootroot00000000000000% tpm2_policytemplate(1) tpm2-tools | General Commands Manual # NAME **tpm2_policytemplate**(1) - Couples a policy with public template data digest of an object. # SYNOPSIS **tpm2_policytemplate** [*OPTIONS*] # DESCRIPTION **tpm2_policytemplate**(1) - Couples a policy with public template data digest of an object. This is a deferred assertion where the hash of the public template data of an object is checked against the one specified in the policy. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **--template-hash**=_FILE_: The file containing the hash of the public template of the object. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES # Restrict the primary object type created under a hierarchy ```bash tpm2_createprimary -C o -c prim.ctx --template-data template.data cat template.data | openssl dgst -sha256 -binary -out template.hash tpm2_startauthsession -S session.ctx -g sha256 tpm2_policytemplate -S session.ctx -L policy.template \ --template-hash template.hash tpm2_flushcontext session.ctx tpm2_setprimarypolicy -C o -g sha256 -L policy.template tpm2_startauthsession -S session.ctx -g sha256 --policy-session tpm2_policytemplate -S session.ctx --template-hash template.hash tpm2_createprimary -C o -c prim2.ctx -P session:session.ctx tpm2_flushcontext session.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_policyticket.1.md000066400000000000000000000061211412464516500203110ustar00rootroot00000000000000% tpm2_ticket(1) tpm2-tools | General Commands Manual # NAME **tpm2_ticket**(1) - Enables policy authorization by verifying a ticket that represents a validated authorization that had an expiration time associated with it. # SYNOPSIS **tpm2_ticket** [*OPTIONS*] # DESCRIPTION **tpm2_ticket**(1) - Enables policy authorization by verifying a ticket that represents a validated authorization that had an expiration time associated with it. # OPTIONS * **-L**, **\--policy**=_FILE_: File to save the compounded policy digest. * **-S**, **\--session**=_FILE_: The policy session file generated via the **-S** option to **tpm2_startauthsession**(1). * **-n**, **\--name**=_FILE_: Name of the object that validated the authorization. * **\--ticket**=_FILE_: The ticket file to record the authorization ticket structure. * **\--timeout**=_FILE_: The file path to record the timeout structure returned. * **-q**, **\--qualification**=_FILE\_OR\_HEX\_STR_: Optional, the policy qualifier data that the signer can choose to include in the signature. Can be either a hex string or path. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES Authorize a TPM operation on an object whose authorization is bound to specific signing authority. ## Create the signing authority and load the verification key ```bash openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem tpm2_loadexternal -C o -G rsa -u public.pem -c signing_key.ctx \ -n signing_key.name ``` ## Generate signature with the expiry time ```bash EXPIRYTIME="FFFFFE0C" echo $EXPIRYTIME | xxd -r -p | \ openssl dgst -sha256 -sign private.pem -out signature.dat ``` ## Create the policy ```bash tpm2_startauthsession -S session.ctx tpm2_policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -L policy.signed tpm2_flushcontext session.ctx ``` ## Create a sealing object ```bash tpm2_createprimary -C o -c prim.ctx -Q echo "plaintext" > secret.dat tpm2_create -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx \ -C prim.ctx -i secret.dat -L policy.signed -Q ``` ## Create ticket-able policy ```bash tpm2_startauthsession -S session.ctx --nonce-tpm=nonce.test --policy-session { cat nonce.test & echo $EXPIRYTIME | xxd -r -p; } | \ openssl dgst -sha256 -sign private.pem -out signature.dat tpm2_policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -x nonce.test --ticket tic.ket --timeout time.out \ -t 0xFFFFFE0C tpm2_flushcontext session.ctx ``` ##Test with policyticket instead of policysigned ```bash tpm2_startauthsession -S session.ctx --policy-session tpm2_policyticket -S session.ctx -n signing_key.name --ticket tic.ket \ --timeout time.out tpm2_unseal -p session:session.ctx -c sealing_key.ctx ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_print.1.md000066400000000000000000000043061412464516500167450ustar00rootroot00000000000000% tpm2_print(1) tpm2-tools | General Commands Manual # NAME **tpm2_print**(1) - Prints TPM data structures # SYNOPSIS **tpm2_print** [*OPTIONS*] [*ARGUMENT* or *STDIN*] # DESCRIPTION **tpm2_print**(1) - Decodes a TPM data structure and prints enclosed elements to stdout as YAML. A file path containing a TPM object may be specified as the path argument. Reads from stdin if unspecified. # OPTIONS * **-t**, **\--type**: Required. Type of data structure. The option supports the following arguments: * **TPMS_ATTEST** * **TPMS_CONTEXT** * **TPM2B_PUBLIC** * **TPMT_PUBLIC** * **ARGUMENT** the command line argument specifies the path of the TPM data. [pubkey options](common/pubkey.md) Public key format. This only works if option `--type/-t` is set to TPM2B_PUBLIC or TPMT_PUBLIC. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Print a TPM Quote ### Setup a key to generate a qoute from ```bash tpm2_createprimary -C e -c primary.ctx tpm2_create -C primary.ctx -u key.pub -r key.priv tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx tpm2_quote -c key.ctx -l 0x0004:16,17,18+0x000b:16,17,18 -g sha256 -m msg.dat ``` ### Print a Quote ```bash tpm2_print -t TPMS_ATTEST msg.dat ``` ### Print a public file ```bash tpm2_print -t TPM2B_PUBLIC key.pub ``` ### Print a tpmt public file ```bash tpm2_readpublic -c key.ctx -f tpmt -o key.tpmt tpm2_print -t TPMT_PUBLIC key.tpmt ``` ### Print a TPM2B_PUBLIC file and convert to PEM format ```bash tpm2 print -t TPM2B_PUBLIC -f pem key.pub ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_quote.1.md000066400000000000000000000054631412464516500167530ustar00rootroot00000000000000% tpm2_quote(1) tpm2-tools | General Commands Manual # NAME **tpm2_quote**(1) - Provide a quote and signature from the TPM. # SYNOPSIS **tpm2_quote** [*OPTIONS*] # DESCRIPTION **tpm2_quote**(1) - Provide quote and signature for given list of PCRs in given algorithm/banks. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object for the quote signing key. * **-p**, **\--auth**=_AUTH_: Specifies the authorization value for AK specified by option **-C**. * **-l**, **\--pcr-list**=_PCR_: The list of PCR banks and selected PCRs' ids for each bank. Also see **NOTES** section below. * **-m**, **\--message**=_FILE_: Message output file, records the quote message that makes up the data that is signed by the TPM. * **-s**, **\--signature**=_FILE_: Signature output file, records the signature in the format specified via the **-f** option. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. * **-o**, **\--pcr**=_FILE_. PCR output file, optional, records the list of PCR values as defined by **-l**. [PCR output file format specifiers](common/pcrs_format.md) Default is 'serialized'. * **-q**, **\--qualification**=_HEX\_STRING\_OR\_PATH_: Data given as a Hex string or binary file to qualify the quote, optional. This is typically used to add a nonce against replay attacks. * **-g**, **\--hash-algorithm**: Hash algorithm for signature. Defaults to sha256. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [signature format specifiers](common/signature.md) option used to configure signature _FORMAT_. [pcr bank specifiers](common/pcr.md) details the syntax for specifying pcr list. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -C e -c primary.ctx tpm2_create -C primary.ctx -u key.pub -r key.priv tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx tpm2_quote -Q -c key.ctx -l 0x0004:16,17,18+0x000b:16,17,18 ``` # NOTES The maximum number of PCR that can be quoted at once is associated with the maximum length of a bank. On most TPMs, it means that this tool can quote up to 24 PCRs at once. That this performs a detached signature. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_rc_decode.1.md000066400000000000000000000014331412464516500175160ustar00rootroot00000000000000% tpm2_rc_decode(1) tpm2-tools | General Commands Manual # NAME **tpm2_rc_decode**(1) - Decode TPM2 error codes to a human readable format. # SYNOPSIS **tpm2_rc_decode** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_rc_decode**(1) - Converts an _RC\_CODE_ from the TPM or TSS2 software stack into human readable errors. Analogous to **strerror**(3), but for the TPM2 stack. # OPTIONS This tool takes no tool specific options. * **ARGUMENT** the command line argument specifies the error code to be parsed. ## References [common options](common/options.md) collection of common options that provide information many users may expect. # EXAMPLES ```bash tpm2_rc_decode 0x1d5 tpm:parameter(1):structure is the wrong size ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_readclock.1.md000066400000000000000000000031371412464516500175410ustar00rootroot00000000000000% tpm2_readclock(1) tpm2-tools | General Commands Manual # NAME **tpm2_readclock**(1) - Retrieves the time information from the TPM. # SYNOPSIS **tpm2_readclock** [*OPTIONS*] # DESCRIPTION **tpm2_readclock**(1) -Reads the current TPMS\_TIME\_INFO structure from the TPM. The structure contains the current setting of Time, Clock, resetCount, and restartCount. The structure is output as YAML to stdout. The YAML output is defined as: ```yaml time: 13673142 # 64 bit value of time TPM has been powered on in ms. clock_info: clock: 13673142 # 64 bit value of time TPM has been powered on since last TPM2_Clear in ms. reset_count: 0 # 32 bit value of the number of TPM Resets since the last # TPM2_Clear. restart_count: 0 # 32 bit value of the number of times that TPM2_Shutdown or # _TPM_Hash_Start have occurred since the last TPM Reset or # TPM2_Clear. safe: yes # boolean yes|no value that no value of Clock greater than # the current value of Clock has been previously reported by # the TPM. ``` This tool takes no arguments and no tool specific options. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Read the clock ```bash tpm2_readclock time: 13673142 clock_info: clock: 13673142 reset_count: 0 restart_count: 0 safe: yes ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_readpublic.1.md000066400000000000000000000061101412464516500177160ustar00rootroot00000000000000% tpm2_readpublic(1) tpm2-tools | General Commands Manual # NAME **tpm2_readpublic**(1) - Read the public area of a loaded object. # SYNOPSIS **tpm2_readpublic** [*OPTIONS*] # DESCRIPTION **tpm2_readpublic**(1) - Reads the public area of a loaded object. # OPTIONS * **-c**, **\--object-context**=_OBJECT_: Context object for the object to read. * **-n**, **\--name**=_FILE_: An optional file to save the name structure of the object. [pubkey options](common/pubkey.md) Public key format. * **-o**, **\--output**=_FILE_: The output file path, recording the public portion of the object. * **-t**, **\--serialized-handle**=_HANDLE_: If the object to be read is a persistent object specified by a raw handle, optionally save the serialized handle for use later. This routine does NOT verify the name of the object being read. Callers should ensure that the contents of name match the expected objects name. * **-q**, **\--qualified-name**=_FILE_: Saves the qualified name of the object to _FILE_. The qualified name of the object is the name algorithm hash of the parents qualified and the objects name. Thus the qualified name of the object serves as proof of the objects parents. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create a primary object and read the public structure in an openssl compliant format ```bash tpm2_createprimary -c primary.ctx tpm2_readpublic -c primary.ctx -o output.dat -f pem ``` ## Serialize an existing persistent object handle to disk for later use This work-flow is primarily intended for existing persistent TPM objects. This work-flow does not verify that the name of the serialized object matches the expected, and thus the serialized handle could be pointing to an attacker controlled object if no verification is done. If you are creating an object from scratch, save the serialized handle when making the object persistent. We assume that an object has already been persisted, for example via: ```bash # We assume that an object has already been persisted, for example tpm2_createprimary -c primary.ctx # context files have all the information for the TPM to verify the object tpm2_evictcontrol -c primary.ctx persistent-handle: 0x81000001 action: persisted ``` Next use the persistent handle to get a serialized handle: ```bash # The persistent handle output could be at an attacker controlled object, # best practice is to use the option "-o: for tpm2_evictcontrol to get a # serialized handle instead. tpm2_readpublic -c 0x81000001 -o output.dat -f pem -t primary.handle # use this verified handle in an encrypted session with the tpm tpm2_startauthsession --policy-session -S session.ctx -c primary.handle ``` For new objects, its best to use all serialized handles. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_rsadecrypt.1.md000066400000000000000000000053721412464516500177750ustar00rootroot00000000000000% tpm2_rsadecrypt(1) tpm2-tools | General Commands Manual # NAME **tpm2_rsadecrypt**(1) - Performs an RSA decryption operation using the TPM. # SYNOPSIS **tpm2_rsadecrypt** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_rsadecrypt**(1) - Performs RSA decryption on the contents of file using the indicated padding scheme according to IETF RFC 3447 (PKCS#1). Command line argument defaults to *stdin* if not specified. The key referenced by key-context is **required** to be: 1. An RSA key 2. Have the attribute *decrypt* **SET** in it's attributes. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object pointing to the the public portion of RSA key to use for decryption. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--auth**=_AUTH_: Optional authorization value to use the key specified by **-c**. * **-o**, **\--output**=_FILE_: Optional output file path to record the decrypted data to. The default is to print the binary encrypted data to _STDOUT_. * **-s**, **\--scheme**=_FORMAT_: Optional, set the padding scheme (defaults to rsaes). * null - TPM_ALG_NULL uses the key's scheme if set. * rsaes - TPM_ALG_RSAES which is RSAES_PKCSV1.5. * oaep - TPM_ALG_OAEP which is RSAES_OAEP. * **-l**, **\--label**=_FILE_ OR _STRING_: Optional, set the label data.The TPM requires the last byte of the label to be zero, this is handled internally to the tool. No other embedded 0 bytes can exist or the TPM will truncate your label. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **ARGUMENT** the command line argument specifies the file containing data to be decrypted. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create an RSA key and load it ```bash tpm2_createprimary -c primary.ctx tpm2_create -C primary.ctx -Grsa2048 -u key.pub -r key.priv tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx ``` ## Encrypt using RSA ```bash echo "my message" > msg.dat tpm2_rsaencrypt -c key.ctx -o msg.enc msg.dat ``` ## Decrypt using RSA ```bash tpm2_rsadecrypt -c key.ctx -o msg.ptext msg.enc cat msg.ptext my message ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_rsaencrypt.1.md000066400000000000000000000045711412464516500200070ustar00rootroot00000000000000% tpm2_rsaencrypt(1) tpm2-tools | General Commands Manual # NAME **tpm2_rsaencrypt**(1) - Performs an RSA encryption operation using the TPM. # SYNOPSIS **tpm2_rsaencrypt** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_rsaencrypt**(1) - Performs RSA encryption on the contents of file data using the indicated padding scheme according to IETF RFC 3447 (PKCS#1). Input defaults to *STDIN* if not specified. The key referenced by key-context is **required** to be: 1. An RSA key 2. Have the attribute *encrypt* **SET** in it's attributes. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object pointing to the the public portion of RSA key to use for encryption. * **-o**, **\--output**=_FILE_: Optional output file path to record the encrypted data to. The default is to print the binary encrypted data to stdout. * **-s**, **\--scheme**=_FORMAT_: Optional, set the padding scheme (defaults to rsaes). * null - TPM_ALG_NULL uses the key's scheme if set. * rsaes - TPM_ALG_RSAES which is RSAES_PKCSV1.5. * oaep - TPM_ALG_OAEP which is RSAES_OAEP. * **-l**, **\--label**=_FILE_ or _STRING_: Optional, set the label data. Can either be a string or file path. The TPM requires the last byte of the label to be zero, this is handled internally to the tool. No other embedded 0 bytes can exist or the TPM will truncate your label. * **ARGUMENT** the command line argument specifies the path of the file with data to be encrypted. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Create an RSA key and load it ```bash tpm2_createprimary -c primary.ctx tpm2_create -C primary.ctx -Grsa2048 -u key.pub -r key.priv tpm2_load -C primary.ctx -u key.pub -r key.priv -c key.ctx ``` ## Encrypt using RSA ```bash echo "my message" > msg.dat tpm2_rsaencrypt -c key.ctx -o msg.enc msg.dat ``` ## Decrypt using RSA ```bash tpm2_rsadecrypt -c key.ctx -o msg.ptext msg.enc cat msg.ptext my message ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_selftest.1.md000066400000000000000000000024071412464516500174420ustar00rootroot00000000000000% tpm2_selftest(1) tpm2-tools | General Commands Manual # NAME **tpm2_selftest**(1) - Run TPM's self-test internal routines # SYNOPSIS **tpm2_selftest** [*OPTIONS*] # DESCRIPTION **tpm2_selftest**(1) - Cause the TPM to execute self-test of its capabilities. Self-test can be executed in two modes : * Simple test - TPM will test functions that require testing * Full test - TPM will test all functions regardless of what has already been tested Once the TPM receives this request, the TPM will return TPM\_RC\_TESTING for any command that requires a test. If a test fails, the TPM will return TPM\_RC\_FAILURE for any command other than TPM2\_GetTestResult() and TPM2\_GetCapability() during this time. The TPM will remain in failure mode until the next TPM initialization. # OPTIONS * **-f**, **\--fulltest** : Run self-test in full mode ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Perform a simple TPM self-test ```bash tpm2_selftest ``` ## Perform a complete TPM self-test ```bash tpm2_selftest -f ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_send.1.md000066400000000000000000000024061412464516500165410ustar00rootroot00000000000000% tpm2_send(1) tpm2-tools | General Commands Manual # NAME **tpm2_send**(1) - Send a raw command buffer to the TPM. # SYNOPSIS **tpm2_send** [*OPTIONS*] [*STDIN*] # DESCRIPTION **tpm2_send**(1) - Sends a TPM command to the TPM. The command is read from a file as a binary stream and transmitted to the TPM using the TCTI specified by the caller. The response received from the TPM is written to the output file. Likely the caller will want to redirect this to a file or into a program to decode and display the response in a human readable form. # OPTIONS * **-o**, **\--output**=_FILE_: Output file to send response buffer to. Defaults to _STDOUT_. * **_STDIN** the file containing the TPM2 command. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Send and receive raw commands to TPM Send the contents of *tpm2-command.bin* to a device and collect the response as *tpm2-response.bin*. ```bash tpm2_send < tpm2-command.bin > tpm2-response.bin tpm2_send < tpm2-command.bin -o tpm2-response.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_sessionconfig.1.md000066400000000000000000000042541412464516500204640ustar00rootroot00000000000000% tpm2_sessionconfig(1) tpm2-tools | General Commands Manual # NAME **tpm2_sessionconfig**(1) - Configure session attributes and print session info from a session file. # SYNOPSIS **tpm2_sessionconfig** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_sessionconfig**(1) - Configure session attributes and print session info from a session file. The tool operates in one of two modes: 1. Configure/ modify the session attributes. 2. Print the session information. This is the default behavior. # OPTIONS * **\--enable-continuesession**: Enable continueSession in the session-attributes. * **\--disable-continuesession** Disable continuesession in the session-attributes. * **\--enable-auditexclusive** Enable auditexclusive in the session-attributes. * **\--disable-auditexclusive** Disable auditexclusive in the session-attributes. * **\--enable-auditreset** Enable auditreset in the session-attributes. * **\--disable-auditreset** Disable auditreset in the session-attributes. * **\--enable-decrypt** Enable decrypt in the session-attributes. * **\--disable-decrypt** Disable decrypt in the session-attributes. * **\--enable-encrypt** Enable encrypt in the session-attributes. * **\--disable-encrypt** Disable encrypt in the session-attributes. * **\--enable-audit** Enable audit in the session-attributes. * **\--disable-audit** Disable audit in the session-attributes. * **ARGUMENT** the session context file. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Start a bounded & salted session, disable continuesession and display session ```bash tpm2 createprimary -c prim.ctx tpm2 startauthsession -S session.ctx --policy-session -c prim.ctx ### Session info before changing attributes tpm2 sessionconfig session.ctx ### Session info after changing attributes tpm2 sessionconfig --disable-continuesession tpm2 sessionconfig session.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_setclock.1.md000066400000000000000000000026611412464516500174220ustar00rootroot00000000000000% tpm2_setclock(1) tpm2-tools | General Commands Manual # NAME **tpm2_setclock**(1) - Sets the time on the TPM. # SYNOPSIS **tpm2_setclock** [*OPTIONS*] __TIME__ # DESCRIPTION **tpm2_setclock**(1) - Sets the clock on the TPM to a time in the **future**. The sole argument is the clock time as a number to set. # OPTIONS * **-c**, **\--hierarchy**=_OBJECT_: The hierarchy to use for authorization, either platform or owner. Defaults to the owner hierarchy if not specified. * **-p**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy specified by option **-c**. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set the clock Set the clock using the owner password. ```bash tpm2_setclock -p ownerpw 13673142 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_setcommandauditstatus.1.md000066400000000000000000000136661412464516500222470ustar00rootroot00000000000000% tpm2_setcommandauditstatus(1) tpm2-tools | General Commands Manual # NAME **tpm2_setcommandauditstatus**(1) - Add or remove TPM2 commands to the audited commands list. # SYNOPSIS **tpm2_setcommandauditstatus** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_setcommandauditstatus**(1) - Add or remove TPM2 commands to the audited commands list. As an argument it takes the command as an integer or friendly string value. Friendly string to COMMAND CODE mapping can be found in section *COMMAND CODE MAPPINGS*. # OPTIONS * **-C**, **\--hierarchy**=_OBJECT_: Specify either owner or platform hierarchy. Defaults to **TPM_RH_OWNER**, when no value has been specified. Supported options are: * **o** for **TPM_RH_OWNER** * **p** for **TPM_RH_PLATFORM** * **-P**, **\--hierarchy-auth**=_AUTH_: Specifies the authorization value for the hierarchy. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-c**, **\--clear-list**: Specifies that the TPM command specified has to be taken off the audit list. When not specified, the default behaviour is to add the TPM command to the audit list. * **-g**, **\--hash-algorithm**=_ALGORITHM_: Sets up the hashing algorithm for the audit digest. When not specified, the default audit digest algorithm is set to SHA256. * **ARGUMENT** the command line argument specifies TPM2 command code. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [hash algorithm options](common/hash.md) collection of options to specify hash algorithm. # COMMAND CODE MAPPINGS The friendly strings below can be used en lieu of the raw integer values. -TPM2\_CC\_AC\_GetCapability: 0x194 -TPM2\_CC\_AC\_Send: 0x195 -TPM2\_CC\_ActivateCredential: 0x147 -TPM2\_CC\_Certify: 0x148 -TPM2\_CC\_CertifyCreation: 0x14a -TPM2\_CC\_ChangeEPS: 0x124 -TPM2\_CC\_ChangePPS: 0x125 -TPM2\_CC\_Clear: 0x126 -TPM2\_CC\_ClearControl: 0x127 -TPM2\_CC\_ClockRateAdjust: 0x130 -TPM2\_CC\_ClockSet: 0x128 -TPM2\_CC\_Commit: 0x18b -TPM2\_CC\_ContextLoad: 0x161 -TPM2\_CC\_ContextSave: 0x162 -TPM2\_CC\_Create: 0x153 -TPM2\_CC\_CreateLoaded: 0x191 -TPM2\_CC\_CreatePrimary: 0x131 -TPM2\_CC\_DictionaryAttackLockReset: 0x139 -TPM2\_CC\_DictionaryAttackParameters: 0x13a -TPM2\_CC\_Duplicate: 0x14b -TPM2\_CC\_ECC\_Parameters: 0x178 -TPM2\_CC\_ECDH\_KeyGen: 0x163 -TPM2\_CC\_ECDH\_ZGen: 0x154 -TPM2\_CC\_EC\_Ephemeral: 0x18e -TPM2\_CC\_EncryptDecrypt: 0x164 -TPM2\_CC\_EncryptDecrypt2: 0x193 -TPM2\_CC\_EventSequenceComplete: 0x185 -TPM2\_CC\_EvictControl: 0x120 -TPM2\_CC\_FieldUpgradeData: 0x141 -TPM2\_CC\_FieldUpgradeStart: 0x12f -TPM2\_CC\_FirmwareRead: 0x179 -TPM2\_CC\_FlushContext: 0x165 -TPM2\_CC\_GetCapability: 0x17a -TPM2\_CC\_GetCommandAuditDigest: 0x133 -TPM2\_CC\_GetRandom: 0x17b -TPM2\_CC\_GetSessionAuditDigest: 0x14d -TPM2\_CC\_GetTestResult: 0x17c -TPM2\_CC\_GetTime: 0x14c -TPM2\_CC\_Hash: 0x17d -TPM2\_CC\_HashSequenceStart: 0x186 -TPM2\_CC\_HierarchyChangeAuth: 0x129 -TPM2\_CC\_HierarchyControl: 0x121 -TPM2\_CC\_HMAC: 0x155 -TPM2\_CC\_HMAC\_Start: 0x15b -TPM2\_CC\_Import: 0x156 -TPM2\_CC\_IncrementalSelfTest: 0x142 -TPM2\_CC\_Load: 0x157 -TPM2\_CC\_LoadExternal: 0x167 -TPM2\_CC\_MakeCredential: 0x168 -TPM2\_CC\_NV\_Certify: 0x184 -TPM2\_CC\_NV\_ChangeAuth: 0x13b -TPM2\_CC\_NV\_DefineSpace: 0x12a -TPM2\_CC\_NV\_Extend: 0x136 -TPM2\_CC\_NV\_GlobalWriteLock: 0x132 -TPM2\_CC\_NV\_Increment: 0x134 -TPM2\_CC\_NV\_Read: 0x14e -TPM2\_CC\_NV\_ReadLock: 0x14f -TPM2\_CC\_NV\_ReadPublic: 0x169 -TPM2\_CC\_NV\_SetBits: 0x135 -TPM2\_CC\_NV\_UndefineSpace: 0x122 -TPM2\_CC\_NV\_UndefineSpaceSpecial: 0x11f -TPM2\_CC\_NV\_Write: 0x137 -TPM2\_CC\_NV\_WriteLock: 0x138 -TPM2\_CC\_ObjectChangeAuth: 0x150 -TPM2\_CC\_PCR\_Allocate: 0x12b -TPM2\_CC\_PCR\_Event: 0x13c -TPM2\_CC\_PCR\_Extend: 0x182 -TPM2\_CC\_PCR\_Read: 0x17e -TPM2\_CC\_PCR\_Reset: 0x13d -TPM2\_CC\_PCR\_SetAuthPolicy: 0x12c -TPM2\_CC\_PCR\_SetAuthValue: 0x183 -TPM2\_CC\_Policy\_AC\_SendSelect: 0x196 -TPM2\_CC\_PolicyAuthorize: 0x16a -TPM2\_CC\_PolicyAuthorizeNV: 0x192 -TPM2\_CC\_PolicyAuthValue: 0x16b -TPM2\_CC\_PolicyCommandCode: 0x16c -TPM2\_CC\_PolicyCounterTimer: 0x16d -TPM2\_CC\_PolicyCpHash: 0x16e -TPM2\_CC\_PolicyDuplicationSelect: 0x188 -TPM2\_CC\_PolicyGetDigest: 0x189 -TPM2\_CC\_PolicyLocality: 0x16f -TPM2\_CC\_PolicyNameHash: 0x170 -TPM2\_CC\_PolicyNV: 0x149 -TPM2\_CC\_PolicyNvWritten: 0x18f -TPM2\_CC\_PolicyOR: 0x171 -TPM2\_CC\_PolicyPassword: 0x18c -TPM2\_CC\_PolicyPCR: 0x17f -TPM2\_CC\_PolicyPhysicalPresence: 0x187 -TPM2\_CC\_PolicyRestart: 0x180 -TPM2\_CC\_PolicySecret: 0x151 -TPM2\_CC\_PolicySigned: 0x160 -TPM2\_CC\_PolicyTemplate: 0x190 -TPM2\_CC\_PolicyTicket: 0x172 -TPM2\_CC\_PP\_Commands: 0x12d -TPM2\_CC\_Quote: 0x158 -TPM2\_CC\_ReadClock: 0x181 -TPM2\_CC\_ReadPublic: 0x173 -TPM2\_CC\_Rewrap: 0x152 -TPM2\_CC\_RSA\_Decrypt: 0x159 -TPM2\_CC\_RSA\_Encrypt: 0x174 -TPM2\_CC\_SelfTest: 0x143 -TPM2\_CC\_SequenceComplete: 0x13e -TPM2\_CC\_SequenceUpdate: 0x15c -TPM2\_CC\_SetAlgorithmSet: 0x13f -TPM2\_CC\_SetCommandCodeAuditStatus: 0x140 -TPM2\_CC\_SetPrimaryPolicy: 0x12e -TPM2\_CC\_Shutdown: 0x145 -TPM2\_CC\_Sign: 0x15d -TPM2\_CC\_StartAuthSession: 0x176 -TPM2\_CC\_Startup: 0x144 -TPM2\_CC\_StirRandom: 0x146 -TPM2\_CC\_TestParms: 0x18a -TPM2\_CC\_Unseal: 0x15e -TPM2\_CC\_Vendor\_TCG\_Test: 0x20000000 -TPM2\_CC\_VerifySignature: 0x177 -TPM2\_CC\_ZGen\_2Phase: 0x18d # EXAMPLES Add TPM2_CC_Unseal to the list of audited commands. ```bash tpm2_setcommandauditstatus TPM2_CC_Unseal ``` [returns](common/returns.md) [limitations](common/policy-limitations.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_setprimarypolicy.1.md000066400000000000000000000040061412464516500212250ustar00rootroot00000000000000% tpm2_setprimarypolicy(1) tpm2-tools | General Commands Manual # NAME **tpm2_setprimarypolicy**(1) - Sets the authorization policy for the lockout (lockoutPolicy), the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the endorsement hierarchy (endorsementPolicy). # SYNOPSIS **tpm2_setprimarypolicy** [*OPTIONS*] # DESCRIPTION **tpm2_setprimarypolicy**(1) - Sets the authorization policy for the lockout (lockoutPolicy), the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and the endorsement hierarchy (endorsementPolicy). # OPTIONS These options control creating the policy authorization session: * **-C**, **\--hierarchy**=_OBJECT_: Specifies the hierarchy whose authorization policy is to be setup. It can be specified as o|p|e|l * **-P**, **\--auth**=_AUTH_: Specifies the authorization value for the hierarchy. * **-L**, **\--policy**=_FILE_: The file path of the authorization policy data. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used in computation of the policy digest. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Set a blank authorization policy for endorsement hierarchy ```bash tpm2_setprimarypolicy -C e ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_shutdown.1.md000066400000000000000000000020411412464516500174560ustar00rootroot00000000000000% tpm2_shutdown(1) tpm2-tools | General Commands Manual # NAME **tpm2_shutdown**(1) - Send a shutdown command to the TPM. # SYNOPSIS **tpm2_shutdown** [*OPTIONS*] # DESCRIPTION **tpm2_shutdown**(1) - Send a **TPM2_Shutdown** command with either **TPM_SU_CLEAR** or **TPM_SU_STATE**. # OPTIONS * **-c**, **\--clear**: Shutdown type sent will be **TPM_SU_CLEAR** instead of **TPM2_SU_STATE**. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Send a TPM Shutdown Command with flags TPM2\_SU\_STATE ```bash tpm2_shutdown ``` ## Send a TPM Shutdown Command with flags TPM2\_SU\_CLEAR ```bash tpm2_shutdown -c ``` # NOTES Typically a Resource Manager (like [tpm2-abrmd](https://github.com/tpm2-software/tpm2-abrmd)) or low-level/boot software will have already sent this command. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_sign.1.md000066400000000000000000000113421412464516500165470ustar00rootroot00000000000000% tpm2_sign(1) tpm2-tools | General Commands Manual # NAME **tpm2_sign**(1) - Sign a hash or message using the TPM. # SYNOPSIS **tpm2_sign** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_sign**(1) - Generates signature of specified message or message-digest using the specified symmetric or asymmetric signing key. When signing a message, **tpm2_sign** utility first calculates the digest of the message similar to the **tpm2_hash** command. It also generates a validation ticket under TPM2_RH_NULL or TPM2_RH_OWNER hierarchies respectively for unrestricted or the restricted signing keys. While signing messages is a provision in this tool it is recommended to use the **tpm2_hash** tool first and pass the digest and validation ticket. NOTE: If the signing key is a restricted signing key, then validation and digest must be provided via the **-t** input. The ticket indicates that the TPM performed the hash of the message. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object pointing to the the key used for signing. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--auth**_AUTH_: Optional authorization value to use the key specified by **-c**. Authorization values should follow the "authorization formatting standards", see section "Authorization Formatting". * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the message. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. * **-s**, **\--scheme**=_ALGORITHM_: The signing scheme used to sign the message. Optional. Signing schemes should follow the "formatting standards", see section "Algorithm Specifiers". If specified, the signature scheme must match the key type. If left unspecified, a default signature scheme for the key type will be used. * **-d**, **\--digest**: Indicate that _FILE_ is a file containing the digest of the message. When this option and **-t** is specified, a warning is generated and the **validation ticket (-t) is ignored**. You cannot use this option to sign a digest against a restricted signing key. * **-t**, **\--ticket**=_FILE_: The ticket file, containing the validation structure, optional. * **-o**, **\--signature**=_FILE_: The signature file, records the signature structure. * **-f**, **\--format**=_FORMAT_: Format selection for the signature output file. See section "Signature Format Specifiers". * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash. * **\--commit-index**=_NATURALNUMBER_ The commit counter value to determine the key index to use in an ECDAA signing scheme. The default counter value is 0. * **ARGUMENT** the command line argument specifies the file data for sign. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [signature format specifiers](common/signature.md) # EXAMPLES ## Sign and verify with the TPM using the *endorsement* hierarchy ```bash tpm2_createprimary -C e -c primary.ctx tpm2_create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx tpm2_load -C primary.ctx -u rsa.pub -r rsa.priv -c rsa.ctx echo "my message" > message.dat tpm2_sign -c rsa.ctx -g sha256 -o sig.rssa message.dat tpm2_verifysignature -c rsa.ctx -g sha256 -s sig.rssa -m message.dat ``` ## Sign with the TPM and verify with OSSL ```bash openssl ecparam -name prime256v1 -genkey -noout -out private.ecc.pem openssl ec -in private.ecc.pem -out public.ecc.pem -pubout # Generate a hash to sign echo "data to sign" > data.in.raw sha256sum data.in.raw | awk '{ print "000000 " $1 }' | \ xxd -r -c 32 > data.in.digest # Load the private key for signing tpm2_loadexternal -Q -G ecc -r private.ecc.pem -c key.ctx # Sign in the TPM and verify with OSSL tpm2_sign -Q -c key.ctx -g sha256 -d -f plain -o data.out.signed data.in.digest openssl dgst -verify public.ecc.pem -keyform pem -sha256 \ -signature data.out.signed data.in.raw ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_startauthsession.1.md000066400000000000000000000106171412464516500212360ustar00rootroot00000000000000% tpm2_startauthsession(1) tpm2-tools | General Commands Manual # NAME **tpm2_startauthsession**(1) - Start a session with the TPM. # SYNOPSIS **tpm2_startauthsession** [*OPTIONS*] # DESCRIPTION **tpm2_startauthsession**(1) - Starts a session with the TPM. The default is to start a *trial* session unless the **-a** option is specified. Saves the policy session data to a file. This file can then be used in subsequent tools that can use a policy file for authorization or policy events. This will not work with resource managers (RMs) outside of [tpm2-abrmd](https:// github.com/tpm2-software/tpm2-abrmd), as most RMs will flush session handles when a client disconnects from the IPC channel. However, when using a RM without the session gapping feature, one can use the command TCTI to keep the connection open. The first step is to create a socket listener that uses tpm2\_send: ```bash mknod "$HOME/backpipe" p while [ 1 ]; do tpm2_send 0<"$HOME/backpipe" | nc -lU "$HOME/sock" 1>"$HOME/backpipe"; done; ``` The next step is to use the command TCTI and netcat (nc) to send data to the socket. ```bash tpm2_startauthsession --tcti="cmd:nc -q 0 -U $HOME/sock" ``` When finishing ensure to kill the listener. For commands executed with the command tcti against the listener, one will need to manage transient handles. The simplest way is to add a flush after each command: `tpm2_flushcontext --tcti="cmd:nc -q 0 -U $HOME/sock" -t` Note: This example uses UNIX sockets, since the socket is controlled with Linux access controls. Using a port is not recommended as it's either open to any user on the system (localhost) or bound to a network card and exposed to the network. This will work with direct TPM access, but note that internally this calls a *ContextSave* and a *ContextLoad* on the session handle, thus the session **cannot** be saved/loaded again. # OPTIONS * **\--policy-session**: Start a policy session of type **TPM_SE_POLICY**. Default without this option is **TPM_SE_TRIAL**. **NOTE**: A *trial* session is used when building a policy and a *policy* session is used when authenticating with a policy. * **\--audit-session**: Start an HMAC session to be used as an audit session. Default without this option is **TPM2_SE_TRIAL**. * **\--hmac-session**: Start an HMAC session of type **TPM_SE_HMAC**. Default without this option is **TPM2_SE_TRIAL**. * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used in computation of the policy digest. * **-c**, **\--key-context**=_OBJECT_: Set the tpmkey and bind objects to be the same. Session parameter encryption is turned on. Session parameter decryption is turned on. Parameter encryption/decryption symmetric-key set to AES-CFB. * **-S**, **\--session**=_FILE_: The name of the policy session file, required. * **\--bind-context**=_FILE_: Set the bind object. Session parameter encryption is off. Use **tpm2_sessionconfig** to turn on. Session parameter decryption is off. Use **tpm2_sessionconfig** to turn on. Parameter encryption/decryption symmetric-key set to AES-CFB. * **\--bind-auth**=_AUTH_: Set the authorization value for the bind object. * **\--tpmkey-context**=_FILE_: Set the tpmkey object. Session parameter encryption is off. Use **tpm2_sessionconfig** to turn on. Session parameter decryption is off. Use **tpm2_sessionconfig** to turn on. Parameter encryption/decryption symmetric-key set to AES-CFB. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Start a *trial* session and save the session data to a file ```bash tpm2_startauthsession -S mysession.ctx ``` ## Start a *policy* session and save the session data to a file ```bash tpm2_startauthsession --policy-session -S mysession.ctx ``` ## Start an encrypted and bound *policy* session and save the session data to a file ```bash tpm2_createprimary -c primary.ctx tpm2_startauthsession --policy-session -c primary.ctx -S mysession.ctx ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_startup.1.md000066400000000000000000000020261412464516500173100ustar00rootroot00000000000000% tpm2_startup(1) tpm2-tools | General Commands Manual # NAME **tpm2_startup**(1) - Send a startup command to the TPM. # SYNOPSIS **tpm2_startup** [*OPTIONS*] # DESCRIPTION **tpm2_startup**(1) - Send a **TPM2_Startup** command with either **TPM_SU_CLEAR** or **TPM_SU_STATE**. # OPTIONS * **-c**, **\--clear**: Startup type sent will be **TPM_SU_CLEAR** instead of **TPM2_SU_STATE**. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ## Send a TPM Startup Command with flags TPM2\_SU\_STATE ```bash tpm2_startup ``` ## Send a TPM Startup Command with flags TPM2\_SU\_CLEAR ```bash tpm2_startup -c ``` # NOTES Typically a Resource Manager (like [tpm2-abrmd](https://github.com/tpm2-software/tpm2-abrmd)) or low-level/boot software will have already sent this command. [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_stirrandom.1.md000066400000000000000000000037751412464516500200040ustar00rootroot00000000000000% tpm2_stirrandom(1) tpm2-tools | General Commands Manual # NAME **tpm2_stirrandom**(1) - Add "additional information" into TPM RNG state. # SYNOPSIS **tpm2_stirrandom** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_stirrandom**(1) - Inject "additional information" as bytes into TPM entropy Protected Capability pool. "Additional information" can be extracted from file specified as argument or being read from *STDIN* if argument is not specified. Up to 128 bytes can be injected at once through standard input to **tpm2_stirrandom**(1). If input file is larger than 128 bytes, **tpm2_stirrandom**(1) will fail. Adding data through **tpm2_stirrandom**(1) will trigger a reseeding of TPM DRBG Protected Capability. It is used when performing any sensitive action on a shielded location such as loading a persistent key or acting on a Protected Capability like updating TPM firmware. # OPTIONS This command has no option ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules.) # EXAMPLES ## Inject from stdin using echo ```bash echo -n "myrandomdata" | tpm2_stirrandom ``` ## Inject 64 bytes from stdin using a file ```bash dd if=/dev/urandom bs=1 count=64 > myrandom.bin tpm2_stirrandom < ./myrandom.bin ``` ## Inject bytes from a file and reading up to 128 bytes ```bash dd if=/dev/urandom of=./myrandom.bin bs=1 count=42 tpm2_stirrandom ./myrandom.bin ``` # NOTES Please be aware that even if the "additional information" added by **tpm2_stirrandom**(1) can be entropy gathered from other DRBG sources, the TPM has no way of determining if the value has any entropy or not. As a consequence, it will just be considered as "additional input". The "additional input" is as defined in [NIST SP800-90A]( https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90.pdf) [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_testparms.1.md000066400000000000000000000023151412464516500176310ustar00rootroot00000000000000% tpm2_testparms(1) tpm2-tools | General Commands Manual # NAME **tpm2_testparms**(1) - Verify that specified algorithm suite is supported by TPM # SYNOPSIS **tpm2_testparms** [*OPTIONS*] [*ARGUMENT*] # DESCRIPTION **tpm2_testparms**(1) - Checks that the suite specified by _ALG\_SPEC_ is available for usage per _ALGORITHM_. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Signing Schemes" for a list of supported hash algorithms. # OPTIONS This tool accepts no tool specific options. ## References [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [signature format specifiers](common/signature.md) # EXAMPLES ## Check whether if "rsa" is supported ```bash tpm2_testparms rsa ``` ## Check that ECDSA using P-256 with AES-128 CTR mode is available ```bash tpm2_testparms ecc256:ecdsa:aes128ctr ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_unseal.1.md000066400000000000000000000044141412464516500171000ustar00rootroot00000000000000% tpm2_unseal(1) tpm2-tools | General Commands Manual # NAME **tpm2_unseal**(1) - Returns a data blob in a loaded TPM object. The data blob is returned in clear. # SYNOPSIS **tpm2_unseal** [*OPTIONS*] # DESCRIPTION **tpm2_unseal**(1) - Returns a data blob in a loaded TPM object. The data blob is returned in clear. The data is sealed at the time of the object creation using the **tpm2_create** tool. Such an object intended for sealing data has to be of the type _TPM\_ALG\_KEYEDHASH_. # OPTIONS * **-c**, **\--object-context**=_OBJECT_: Object context for the loaded object. * **-p**, **\--auth**=_AUTH_: Optional auth value to use for the key specified by **-c**. * **-o**, **\--output**=_FILE_: Output file name containing the unsealed data. Defaults to _STDOUT_ if not specified. * **\--cphash**=_FILE_ File path to record the hash of the command parameters. This is commonly termed as cpHash. NOTE: When this option is selected, The tool will not actually execute the command, it simply returns a cpHash, it simply returns a cpHash, unless rphash is also required. * **\--rphash**=_FILE_ File path to record the hash of the response parameters. This is commonly termed as rpHash. * **-S**, **\--session**=_FILE_: The session created using **tpm2_startauthsession**. Multiple of these can be specified. For example, you can have one session for auditing and another for encryption/decryption of the parameters. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [authorization formatting](common/authorizations.md) details the methods for specifying _AUTH_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -c primary.ctx -Q tpm2_pcrread -Q -o pcr.bin sha256:0,1,2,3 tpm2_createpolicy -Q --policy-pcr -l sha256:0,1,2,3 -f pcr.bin -L pcr.policy echo 'secret' | tpm2_create -C primary.ctx -L pcr.policy -i-\ -u seal.pub -r seal.priv -c seal.ctx -Q tpm2_unseal -c seal.ctx -p pcr:sha256:0,1,2,3 ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_verifysignature.1.md000066400000000000000000000077341412464516500210470ustar00rootroot00000000000000% tpm2_verifysignature(1) tpm2-tools | General Commands Manual # NAME **tpm2_verifysignature**(1) - Validates a signature using the TPM. # SYNOPSIS **tpm2_verifysignature** [*OPTIONS*] # DESCRIPTION **tpm2_verifysignature**(1) - Uses loaded keys to validate a signature on a message with the message digest passed to the TPM. If the signature check succeeds, then the TPM will produce a **TPMT_TK_VERIFIED**. Otherwise, the TPM shall return **TPM_RC_SIGNATURE**. If object references an asymmetric key, only the public portion of the key needs to be loaded. If object references a symmetric key, both the public and private portions need to be loaded. # OPTIONS * **-c**, **\--key-context**=_OBJECT_: Context object for the key context used for the operation. Either a file or a handle number. See section "Context Object Format". * **-g**, **\--hash-algorithm**=_ALGORITHM_: The hash algorithm used to digest the message. Algorithms should follow the "formatting standards", see section "Algorithm Specifiers". Also, see section "Supported Hash Algorithms" for a list of supported hash algorithms. * **-m**, **\--message**=_FILE_: The message file, containing the content to be digested. * **-d**, **\--digest**=_FILE_: The input hash file, containing the hash of the message. If this option is selected, then the message (**-m**) and algorithm (**-g**) options do not need to be specified. * **-s**, **\--signature**=_FILE_: The input signature file of the signature to be validated. * **-f**, **\--scheme**=_SCHEME_: The signing scheme that was used to sign the message. This option should only be specified if the signature comes in from a non *tss* standard, like openssl. See "Signature format specifiers" for more details. The *tss* format contains the signature metadata required to understand it's signature scheme. Signing schemes should follow the "formatting standards", see section "Algorithm Specifiers". * **\--format**=_SCHEME_: Deprecated. Same as **\--scheme**. * **-t**, **\--ticket**=_FILE_: The ticket file to record the validation structure. ## References [context object format](common/ctxobj.md) details the methods for specifying _OBJECT_. [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. [signature format specifiers](common/signature.md) # EXAMPLES ## Sign and verify with the TPM using the *endorsement* hierarchy ```bash tpm2_createprimary -C e -c primary.ctx tpm2_create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx tpm2_load -C primary.ctx -u rsa.pub -r rsa.priv -c rsa.ctx echo "my message > message.dat tpm2_sign -c rsa.ctx -g sha256 -m message.dat -s sig.rssa tpm2_verifysignature -c rsa.ctx -g sha256 -m message.dat -s sig.rssa ``` ## Sign with openssl and verify with the TPM ```bash # Generate an ECC key openssl ecparam -name prime256v1 -genkey -noout -out private.ecc.pem openssl ec -in private.ecc.pem -out public.ecc.pem -pubout # Generate a hash to sign (OSSL needs the hash of the message) echo "data to sign" > data.in.raw sha256sum data.in.raw | awk '{ print "000000 " $1 }' | \ xxd -r -c 32 > data.in.digest # Load the private key for signing tpm2_loadexternal -Q -G ecc -r private.ecc.pem -c key.ctx # Sign in the TPM and verify with OSSL tpm2_sign -Q -c key.ctx -g sha256 -d data.in.digest -f plain -s data.out.signed openssl dgst -verify public.ecc.pem -keyform pem -sha256 \ -signature data.out.signed data.in.raw # Sign with openssl and verify with TPM openssl dgst -sha256 -sign private.ecc.pem -out data.out.signed data.in.raw tpm2_verifysignature -Q -c key.ctx -g sha256 -m data.in.raw -f ecdsa \ -s data.out.signed ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tpm2_zgen2phase.1.md000066400000000000000000000040631412464516500176570ustar00rootroot00000000000000% tpm2_zgen2phase(1) tpm2-tools | General Commands Manual # NAME **tpm2_zgen2phase**(1) - Command to enable the TPM to combine data from the other party with the ephemeral key generated in the first phase of two-phase key exchange protocols. # SYNOPSIS **tpm2_zgen2phase** [*OPTIONS*] # DESCRIPTION **tpm2_zgen2phase**(1) - Command to enable the TPM to combine data from the other party with the ephemeral key generated in the first phase of two-phase key exchange protocols. # OPTIONS * **-c**, **\--key-context**=_FILE_: Context object pointing to ECC key. Either a file or a handle number. See section "Context Object Format". * **-p**, **\--key-auth**=_AUTH_: The authorization value for the ECC key object. * **-s**, **\--scheme**=_ALGORITHM_: The key exchange scheme. Optional. Valid options are ecdh or sm2. * **-t**, **\--counter**=_NATURALNUMBER_: The commit count to determine the key index to use. * **\--static-public**=_FILE_: The static public key input of the other party. * **\--ephemeral-public**=_FILE_: The ephemeral public key input of the other party. * **\--output-Z1**=_FILE_ Specify file path to save the calculated ecdh secret Z1 point. * **\--output-Z2**=_FILE_ Specify file path to save the calculated ecdh secret Z2 point. ## References [algorithm specifiers](common/alg.md) details the options for specifying cryptographic algorithms _ALGORITHM_. [common options](common/options.md) collection of common options that provide information many users may expect. [common tcti options](common/tcti.md) collection of options used to configure the various known TCTI modules. # EXAMPLES ```bash tpm2_createprimary -C o -c prim.ctx -Q tpm2_create -C prim.ctx -c key.ctx -u key.pub -r key.priv -G ecc256:ecdh -Q tpm2_ecephemeral -u ecc.q -t ecc.ctr ecc256 tpm2_ecdhkeygen -u ecdh.pub -o ecdh.priv -c key.ctx tpm2_zgen2phase -c key.ctx --static-public ecdh.pub --ephemeral-public ecc.q \ -t 0 --output-Z1 z1.bin --output-Z2 z2.bin ``` [returns](common/returns.md) [footer](common/footer.md) tpm2-tools-5.2/man/tss2_authorizepolicy.1.md000066400000000000000000000024471412464516500210600ustar00rootroot00000000000000% tss2_authorizepolicy(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_authorizepolicy**(1) - # SYNOPSIS **tss2_authorizepolicy** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_authorizepolicy**(1) - This command signs a given policy with a given key such that the policy can be referenced from other policies that contain a corresponding PolicyAuthorize elements. The signature is done using the TPM signing schemes as specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-P**, **\--policyPath**=_STRING_: Path of the new policy. A policyPath is composed of two elements, separated by "/". A policyPath starts with "/policy". The second path element identifies the policy or policy template using a meaningful name. * **-p**, **\--keyPath**=_STRING_: Path of the signing key. * **-r**, **\--policyRef**=_FILENAME_ or _-_ (for stdin): A byte buffer to be included in the signature. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_authorizepolicy --keyPath=HS/SRK/myPolicySignKey --policyPath=/policy/pcr-policy --policyRef=policyRef.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_changeauth.1.md000066400000000000000000000025711412464516500177330ustar00rootroot00000000000000% tss2_changeauth(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_changeauth**(1) - This command changes the authorization data of an entity referred to by the path. # SYNOPSIS **tss2_changeauth** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_changeauth**(1) - # OPTIONS These are the available options: * **-a**, **\--authValue**=_STRING_: The new UTF-8 password. Optional parameter. If it is neglected then the user is queried interactively for a password. To set no password, this option should be used with the empty string (""). The maximum password size is determined by the digest size of the chosen name hash algorithm in the cryptographic profile (cf., **fapi-profile(5)**). For example, choosing SHA256 as hash algorithm, allows passwords of a maximum size of 32 characters. * **-p**, **\--entityPath**=_STRING_: The path identifying the entity to modify. [common tss2 options](common/tss2-options.md) # EXAMPLES ## Change a password for an entity HS/SRK/myRSACryptKey to M1 ``` tss2_changeauth --entityPath=HS/SRK/myRSACryptKey --authValue=M1 ``` ## Change a password for an entity HS/SRK/myRSACryptKey and ask the user to enter the password. ``` tss2_changeauth --entityPath=HS/SRK/myRSACryptKey ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_createkey.1.md000066400000000000000000000057371412464516500176070ustar00rootroot00000000000000% tss2_createkey(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_createkey**(1) - # SYNOPSIS **tss2_createkey** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_createkey**(1) - This commands creates a key inside the TPM and stores it in the FAPI metadata store and if requested persistently inside the TPM. Depending on the specified key type, cryptographic algorithms and parameters for the created key are determined by the corresponding cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: The path to the new key. * **-t**, **\--type**=_STRING_: Identifies the intended usage. Optional parameter. Types may be any comma-separated combination of: - "sign": Sets the sign attribute of a key. - "decrypt": Sets the decrypt attribute of a key. - Hint: If neither sign nor decrypt are provided, both attributes are set. - "restricted": Sets the restricted attribute of a key. - Hint: If restricted is set, sign or decrypt (but not both) need to be set. - "exportable": Clears the fixedTPM and fixedParent attributes of a key or sealed object. - "noda": Sets the noda attribute of a key or NV index. - "system": Stores the data blobs and metadata for a created key or seal in the system-wide directory instead of user's personal directory. - A hexadecimal number (e.g. "0x81000001"): Marks a key object to be made persistent and sets the persistent object handle to this value. * **-P**, **\--policyPath**=_STRING_: The policy to be associated with the new key. Optional parameter. If omitted then no policy will be associated with the key. A policyPath is composed of two elements, separated by "/". A policyPath starts with "/policy". The second path element identifies the policy or policy template using a meaningful name. * **-a**, **\--authValue**=_STRING_: The new UTF-8 password. Optional parameter. If it is neglected then the user is queried interactively for a password. To set no password, this option should be used with the empty string (""). The maximum password size is determined by the digest size of the chosen name hash algorithm in the cryptographic profile (cf., **fapi-profile(5)**). For example, choosing SHA256 as hash algorithm, allows passwords of a maximum size of 32 characters. [common tss2 options](common/tss2-options.md) # EXAMPLE ## Create a key without password ``` tss2_createkey --path=HS/SRK/myRsaCryptKey --type="noDa, decrypt" --authValue="" ``` ## Create a key, ask for password on the command line ``` tss2_createkey --path=HS/SRK/myRsaCryptKey --type="noDa, decrypt" ``` ## Create a key with password "abc". ``` tss2_createkey --path=HS/SRK/myRsaCryptKey --type="noDa, decrypt" --authValue=abc ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_createnv.1.md000066400000000000000000000051471412464516500174350ustar00rootroot00000000000000% tss2_createnv(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_createnv**(1) - # SYNOPSIS **tss2_createnv** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_createnv**(1) - This command creates an NV index in the TPM. # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: Path of the new NV space. The path is composed of three elements, separated by "/". An nvPath starts with "/nv". The second path element identifies the NV handle range for the nv object. This includes the following values: Owner, TPM, Platform, Endorsement_Certificate, Platform_Certificate, Component_OEM, TPM_OEM, Platform_OEM, PC-Client, Server, Virtualized_Platform, MPWG, Embedded. The third path element identifies the actual NV-Index using a meaningful name. * **-t**, **\--type**=_STRING_: Identifies the intended usage. Optional parameter. Types may be any comma-separated combination of: - "noda": Sets the noda attribute of a key or NV index. - "bitfield": Sets the NV type to bitfield. - "counter": Sets the NV type to counter. - "pcr": Sets the NV type to pcr-like behavior. - Hint: If none of the previous three keywords is provided a regular NV index is created. * **-s**, **\--size**=_INTEGER_: The size in bytes of the NV index to be created. Can be omitted if size can be inferred from the type; e.g. an NV index of type counter has a size of 8 bytes. * **-P**, **\--policyPath**=_STRING_: Identifies the policy to be associated with the new NV space. Optional parameter. If omitted then no policy will be associated with the key. A policyPath is composed of two elements, separated by "/". A policyPath starts with "/policy". The second path element identifies the policy or policy template using a meaningful name. * **-a**, **\--authValue**=_STRING_: The new UTF-8 password. Optional parameter. If it is neglected then the user is queried interactively for a password. To set no password, this option should be used with the empty string (""). The maximum password size is determined by the digest size of the chosen name hash algorithm in the cryptographic profile (cf., **fapi-profile(5)**). For example, choosing SHA256 as hash algorithm, allows passwords of a maximum size of 32 characters. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_createnv --authValue=abc --path=/nv/Owner/myNV --size=20 --type="noDa" ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_createseal.1.md000066400000000000000000000054061412464516500177340ustar00rootroot00000000000000% tss2_createseal(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_createseal**(1) - # SYNOPSIS **tss2_createseal** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_createseal**(1) - This command creates a sealed object and stores it in the FAPI metadata store. If no data is provided (i.e. a NULL-pointer) then the TPM generates random data and fills the sealed object. TPM signing schemes are used as specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: The path to the new key. * **-t**, **\--type**=_STRING_: Identifies the intended usage. Optional parameter. Types may be any comma-separated combination of: - "exportable": Clears the fixedTPM and fixedParent attributes of a key or sealed object. - "noda": Sets the noda attribute of a key or NV index. - "system": Stores the data blobs and metadata for a created key or seal in the system-wide directory instead of user's personal directory. - A hexadecimal number (e.g. "0x81000001"): Marks a key object to be made persistent and sets the persistent object handle to this value. * **-P**, **\--policyPath**=_STRING_: Identifies the policy to be associated with the new key. Optional parameter. If omitted then no policy will be associated with the key. A policyPath is composed of two elements, separated by "/". A policyPath starts with "/policy". The second path element identifies the policy or policy template using a meaningful name. * **-a**, **\--authValue**=_STRING_: The new UTF-8 password. Optional parameter. If it is neglected then the user is queried interactively for a password. To set no password, this option should be used with the empty string (""). The maximum password size is determined by the digest size of the chosen name hash algorithm in the cryptographic profile (cf., **fapi-profile(5)**). For example, choosing SHA256 as hash algorithm, allows passwords of a maximum size of 32 characters. * **-i**, **\--data**=_FILENAME_ or _-_ (for stdin): The data to be sealed by the TPM. Optional parameter. Must not be used together with \--size. * **-s**, **\--size**=_INTEGER_: Determines the number of random bytes the TPM should generate and seal. Optional parameter. Must not be "0". Must no be used together with \--data. [common tss2 options](common/tss2-options.md) # EXAMPLE ## Create a key with password "abc" and read sealing data from file. ``` tss2_createseal --path=HS/SRK/mySealKey --type="noDa" --authValue=abc --data=data.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_decrypt.1.md000066400000000000000000000020401412464516500172650ustar00rootroot00000000000000% tss2_decrypt(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_decrypt**(1) - decrypts data # SYNOPSIS **tss2_decrypt** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_decrypt**(1) - This command decrypts data that was encrypted using tss2_encrypt using the TPM decryption schemes as specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-p**, **\--keyPath**=_STRING_: Identifies the decryption key. * **-i**, **\--cipherText**=_FILENAME_ or _-_ (for stdin): The JSON-encoded cipherText. * **-f**, **\--force**: Force Overwriting the output file. * **-o**, **\--plainText**=_FILENAME_ or _-_ (for stdout): Returns the decrypted data. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_decrypt --keyPath=HS/SRK/myRSACrypt --cipherText=cipherText.file --plainText=plainText.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_delete.1.md000066400000000000000000000023221412464516500170600ustar00rootroot00000000000000% tss2_delete(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_delete**(1) - # SYNOPSIS **tss2_delete** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_delete**(1) - This command deletes the given key, policy or NV from the FAPI metadata store and the TPM. Depending on the entity type, one of the following actions are taken: - Non-persistent key: Flush from TPM (if loaded) and delete public and private blobs from keystore. - Persistent keys: Evict from TPM and delete public and private blobs from keystore - Primary keys: Flush from TPM and delete public blob from keystore - NV index: Undefine NV index from TPM and delete public blob from FAPI metadata store - Policies: Delete entry from policy store - Hierarchy, PCR: These are not deletable - Special keys ek, srk: These are not deletable # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: The path to the entity to delete. [common tss2 options](common/tss2-options.md) # EXAMPLE # Deletes storage hierarchy (HS) and everything below it: ``` tss2_delete --path=/HS ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_encrypt.1.md000066400000000000000000000020071412464516500173020ustar00rootroot00000000000000% tss2_encrypt(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_encrypt**(1) - encrypts data # SYNOPSIS **tss2_encrypt** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_encrypt**(1) - This command encrypts the provided data for a target key using the TPM encryption schemes as specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-p**, **\--keyPath**=_STRING_: Identifies the encryption key. * **-f**, **\--force**: Force overwriting the output file. * **-i**, **\--plainText**=_FILENAME_ or _-_ (for stdin): The data to be encrypted. * **-o**, **\--cipherText**=_FILENAME_ or _-_ (for stdout): Returns the JSON-encoded ciphertext. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_encrypt --keyPath=HS/SRK/myRSACrypt --plainText=plainText.file --cipherText=cipherText.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_exportkey.1.md000066400000000000000000000025041412464516500176520ustar00rootroot00000000000000% tss2_exportkey(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_exportkey**(1) - # SYNOPSIS **tss2_exportkey** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_exportkey**(1) - This command will duplicate a key and encrypt it using the public key of a new parent. The exported data will contain the re-wrapped key pointed to by the pathOfKeyToDuplicate and then the JSON encoded policy. Encryption is done according to TPM encryption schemes specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-e** **\--pathToPublicKeyOfNewParent**=_STRING_: The path to the public key of the new parent. This key MAY be in the public key hierarchy /ext. Optional parameter. If omitted only the public key will exported. * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--exportedData**=_FILENAME_ or _-_ (for stdout): Returns the exported subtree. * **-p**, **\--pathOfKeyToDuplicate**=_STRING_: The path to the root of the subtree to export. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_exportkey --pathOfKeyToDuplicate=HS/SRK/myRSADecrypt --exportedData=exportedData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_exportpolicy.1.md000066400000000000000000000014531412464516500203630ustar00rootroot00000000000000% tss2_policyexport(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_policyexport**(1) - # SYNOPSIS **tss2_policyexport** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_policyexport**(1) - This commands exports a policy associated with a key in JSON encoding. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--jsonPolicy**=_FILENAME_ or _-_ (for stdout): Returns the JSON-encoded policy. * **-p**, **\--path**=_STRING_: The path of the key. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_exportpolicy --path=HS/SRK/myRSASign --jsonPolicy=jsonPolicy.json ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getappdata.1.md000066400000000000000000000015361412464516500177360ustar00rootroot00000000000000% tss2_getappdata(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getappdata**(1) # SYNOPSIS **tss2_getappdata** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getappdata**(1) - This command returns the previously stored application data for an object. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--path**=_STRING_: Path of the object for which the application data will be loaded. * **-o**, **\--appData**=_FILENAME_ or _-_ (for stdout): Returns a copy of the stored data. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getappdata --path=HS/SRK/myRSACrypt --appData=appData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getcertificate.1.md000066400000000000000000000016461412464516500206100ustar00rootroot00000000000000% tss2_getcertificate(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getcertificate**(1) - # SYNOPSIS **tss2_getcertificate** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getcertificate**(1) - This command returns the PEM encoded X.509 certificate associated with the key at path. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--path**=_STRING_: The entity whose certificate is requested. * **-o**, **\--x509certData**=_FILENAME_ or _-_ (for stdout): Returns the PEM encoded certificate. If no certificate is stored, then an empty string is returned. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getcertificate --path=HS/SRK/myRSACrypt --x509certData=x509certData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getdescription.1.md000066400000000000000000000016261412464516500206470ustar00rootroot00000000000000% tss2_getdescription(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getdescription**(1) # SYNOPSIS **tss2_getdescription** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getdescription**(1) - This command returns the previously stored application data for an object. If no description is present, an empty string is returned. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--path**=_STRING_: The path of the object for which the description will be loaded. * **-o**, **\--description**=_FILENAME_ or _-_ (for stdout): Returns the stored description. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getdescription --path=HS/SRK --description=description.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getinfo.1.md000066400000000000000000000014061412464516500172530ustar00rootroot00000000000000% tss2_getinfo(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getinfo**(1) - # SYNOPSIS **tss2_getinfo** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getinfo**(1) - This command returns a UTF-8 string identifying the version of the FAPI, the TPM, configurations and other relevant information in a human readable format. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--info**=_FILENAME_ or _-_ (for stdout): Returns the FAPI and TPM information. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getinfo --info=info.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getplatformcertificates.1.md000066400000000000000000000020061412464516500225270ustar00rootroot00000000000000% tss2_getplatformcertificates(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getplatformcertificates**(1) - # SYNOPSIS **tss2_getplatformcertificates** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getplatformcertificates**(1) - This command returns the set of platform certificates concatenated in a continuous buffer if the platform provides platform certificates. Platform certificates for TPM 2.0 can consist not only of a single certificate but also a series of so-called delta certificates. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--certificates**=_FILENAME_ or _-_ (for stdout): Returns a continuous buffer containing the concatenated platform certificates. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getplatformcertificates --certificates=certificates.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_getrandom.1.md000066400000000000000000000015501412464516500176000ustar00rootroot00000000000000% tss2_getrandom(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_getrandom**(1) - # SYNOPSIS **tss2_getrandom** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_getrandom**(1) - This command uses the TPM to create an array of random bytes. # OPTIONS These are the available options: * **-n**, **\--numBytes**=_INTEGER_: The number of bytes requested by the caller. * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--data**=_FILENAME_ or _-_ (for stdout): The returned random bytes. * **\--hex** Convert the output data to hex format without a leading "0x". [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_getrandom --numBytes=20 -data=- | hexdump -C ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_gettpmblobs.1.md000066400000000000000000000025661412464516500201520ustar00rootroot00000000000000% tss2_gettpmblobs(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_gettpmblobs**(1) - # SYNOPSIS **tss2_gettpmblobs** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_gettpmblobs**(1) - This command returns the public and private blobs of an object, such that they could be loaded by a low-level API (e.g. ESAPI). It also returns the policy associated with these blobs in JSON format. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--path**=_STRING_: The path of the object for which the blobs will be returned. * **-u**, **\--tpm2bPublic**=_FILENAME_ or _-_ (for stdout): The returned public area of the object as a marshalled TPM2B_PUBLIC. Optional parameter. * **-r**, **\--tpm2bPrivate**=_FILENAME_ or _-_ (for stdout): The returned private area of the object as a marshalled TPM2B_PRIVATE. Optional parameter. * **-l**, **\--policy**=_FILENAME_ or _-_ (for stdout): The returned policy associated with the object, encoded in JSON. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_gettpmblobs --path=HS/SRK/myRSACrypt --tpm2bPublic=tpm2bPublic.file --tpm2bPrivate=tpm2bPrivate.file --policy=policy.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_import.1.md000066400000000000000000000015501412464516500171320ustar00rootroot00000000000000% tss2_import(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_import**(1) - # SYNOPSIS **tss2_import** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_import**(1) - This command imports a JSON encoded policy or policy template and stores it under the provided path or it imports a JSON encoded key under the provided path. # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: The path of the new object. * **-i**, **\--importData**=_FILENAME_ or _-_ (for stdin): The data to be imported. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_import --path=/policy/duplicate-policy --importData=importData.json ``` ``` tss2_import --path=/ext/key --importData=importData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_list.1.md000066400000000000000000000020741412464516500165750ustar00rootroot00000000000000% tss2_list(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_list**(1) - # SYNOPSIS **tss2_list** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_list**(1) - This command enumerates all objects in the FAPI metadata store in a given a path. # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--searchPath**=_STRING_: The path identifying the root of the search. Optional parameter. If omitted, all entities will be searched. * **-o**, **\--pathList**=_FILENAME_ or _-_ (for stdout): Returns the colon-separated list of paths. Optional parameter. If omitted, results will be printed to _-_ (stdout). [common tss2 options](common/tss2-options.md) # EXAMPLES ## List all entities and print results to stdout ``` tss2_list ``` ## List all entities under the HS path and print results to file ``` tss2_list --searchPath=HS --pathList=output.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_nvextend.1.md000066400000000000000000000016611412464516500174560ustar00rootroot00000000000000% tss2_nvextend(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_nvextend**(1) - # SYNOPSIS **tss2_nvextend** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_nvextend**(1) - This command performs an extend operation on an NV index (i.e. an NV index that behaves similar to a PCR). # OPTIONS These are the available options: * **-i**, **\--data**=_FILENAME_ or _-_ (for stdin): The data to be extended into the NV space. * **-p**, **\--nvPath**=_STRING_: Identifies the NV space to write. * **-l**, **\--logData**=_FILENAME_ or _-_ (for stdin): A JSON representation of data to be written to the PCR's event log. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_nvextend --nvPath=/nv/Owner/NvExtend --data=data.file --logData=logData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_nvincrement.1.md000066400000000000000000000011651412464516500201520ustar00rootroot00000000000000% tss2_nvincrement(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_nvincrement**(1) - # SYNOPSIS **tss2_nvincrement** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_nvincrement**(1) - This command increments by 1 an NV index that is of type counter. # OPTIONS These are the availabe options: * **-p**, **\--nvPath**=_STRING_: Identifies the NV space to increment. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_nvincrement --nvPath=/nv/Owner/myNVcounter ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_nvread.1.md000066400000000000000000000017001412464516500170740ustar00rootroot00000000000000% tss2_nvread(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_nvread**(1) - # SYNOPSIS **tss2_nvread** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_nvread**(1) - This command reads the entire data from an NV index of the TPM. # OPTIONS These are the availabe options: * **-f**, **\--force**: Force overwriting the output file. * **-o**, **\--data**=_FILENAME_ or _-_ (for stdout): Returns the value read from the NV space. * **-p**, **\--nvPath**=_STRING_: Identifies the NV space to read. * **-l**, **\--logData**=_FILENAME_ or _-_ (for stdout): Returns the JSON encoded log, if the NV index is of type "extend" and an empty string otherwise. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_nvread --nvPath=/nv/Owner/myNV --data=data.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_nvsetbits.1.md000066400000000000000000000015311412464516500176400ustar00rootroot00000000000000% tss2_nvsetbits(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_nvsetbits**(1) - # SYNOPSIS **tss2_nvsetbits** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_nvsetbits**(1) - This command sets bits in an NV Index that was created as a bit field. Any number of bits from 0 to 64 may be set. The contents of bitmap are ORed with the current contents of the NV Index. # OPTIONS These are the availabe options: * **-i**, **\--bitmap**=_BITS_: A mask indicating which bits to set in the NV space. * **-p**, **\--nvPath**=_STRING_: Identifies the NV space to write. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_nvsetbits --nvPath=/nv/Owner/NvBitmap --bitmap=0x0102030405060608 ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_nvwrite.1.md000066400000000000000000000016071412464516500173210ustar00rootroot00000000000000% tss2_nvwrite(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_nvwrite**(1) - # SYNOPSIS **tss2_nvwrite** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_nvwrite**(1) - This command writes data to a "regular" (not pin, extend or counter) NV index. Only the full index can be written, partial writes are not allowed. If the provided data is smaller than the NV index's size, then it is padded up with zero bytes at the end. # OPTIONS These are the available options: * **-i**, **\--data**=_FILENAME_ or _-_ (for stdin): The data to write to the NV space. * **-p**, **\--nvPath**=_STRING_: Identifies the NV space to write to. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_nvwrite --nvPath=/nv/Owner/myNV --data=data.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_pcrextend.1.md000066400000000000000000000017671412464516500176260ustar00rootroot00000000000000% tss2_pcrextend(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_pcrextend**(1) - # SYNOPSIS **tss2_pcrextend** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_pcrextend**(1) - This command extends the data into the PCR listed. The parameter logData is extended into the PCR log. If the logData is NULL, only the PCR extend takes place. All PCRs currently active in the TPM are extended. # OPTIONS These are the available options: * **-x**, **\--pcr**=_INTEGER_: The PCR to extend. * **-i**, **\--data**=_FILENAME_ or _-_ (for stdin): The event data to be extended. * **-l**, **\--logData**=_FILENAME_ or _-_ (for stdin): Contains a JSON representation of data to be written to the PCR's event log. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_pcrextend --pcr=16 --data=data.file --logData=logData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_pcrread.1.md000066400000000000000000000027141412464516500172430ustar00rootroot00000000000000% tss2_pcrread(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_pcrread**(1) - # SYNOPSIS **tss2_pcrread** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_pcrread**(1) - This command provides a PCRs value and corresponding event log. The PCR bank to be used per PCR is defined in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-o**, **\--pcrValue**=_FILENAME_ or _-_ (for stdout): Returns PCR digest. Optional parameter. * **-x**, **\--pcrIndex**=_INTEGER_: Identifies the PCR to read. * **-f**, **\--force**: Force overwriting the output files. * **-l**, **\--pcrLog**=_FILENAME_ or _-_ (for stdout): Returns the PCR log for that PCR. Optional parameter. PCR event logs are a list (arbitrary length JSON array) of log entries with the following content. - recnum: Unique record number - pcr: PCR index - digest: The digests - type: The type of event. At the moment the only possible value is: "LINUX_IMA" (legacy IMA) - eventDigest: Digest of the event; e.g. the digest of the measured file - eventName: Name of the event; e.g. the name of the measured file. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_pcrread --pcrIndex=16 --pcrValue=pcrValue.file --pcrLog=pcrLog.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_provision.1.md000066400000000000000000000037001412464516500176470ustar00rootroot00000000000000% tss2_provision(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_provision**(1) - # SYNOPSIS **tss2_provision** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_provision**(1) - This command provisions a FAPI instance and its associated TPM. The steps taken are: * Retrieve the EK template, nonce and certificate, verify that they match the TPM's EK and store them in the key store. * Set the authValues and policies for the Owner (Storage Hierarchy), the Privacy Administrator (Endorsement Hierarchy) and the lockout authority. * Scan the TPM's nv indices and create entries in the FAPI metadata store. This operation MAY use a heuristic to guess the originating programs for nv indices found and name the entries accordingly. * Create the SRK (storage primary key) inside the TPM and make it persistent if required by the cryptographic profile (cf., **fapi-profile(5)**) and store its metadata in the system-wide FAPI metadata store. Note that the SRK will not have an authorization value associated. If an authorization value is associated with the storage hierarchy, it is highly recommended that the SRK without authorization value is made persistent. The paths of the different metadata storages for keys and nv indices are configured in the FAPI configuration file (cf., **fapi-config(5)**). # OPTIONS These are the available options: * **-E**, **\--authValueEh**=_STRING_: The authorization value for the privacy admin, i.e. the endorsement hierarchy. Optional parameter. * **-S**, **\--authValueSh**=_STRING_: The authorization value for the owner, i.e. the storage hierarchy. Optional parameter. * **-L**, **\--authValueLockout**=_STRING_: The authorization value for the lockout authorization. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_provision ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_quote.1.md000066400000000000000000000042461412464516500167620ustar00rootroot00000000000000% tss2_quote(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_quote**(1) - # SYNOPSIS **tss2_quote** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_quote**(1) - This command performs an attestation using the TPM. The PCR bank for each provided PCR index and signing scheme are set in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-x**, **\--pcrList**=_STRING_: An array holding the PCR indices to quote against. * **-Q**, **\--qualifyingData**=_FILENAME_ or _-_ (for stdin): A nonce provided by the caller to ensure freshness of the signature. Optional parameter. * **-l**, **\--pcrLog**=_FILENAME_ or _-_ (for stdout): Returns the PCR log for the chosen PCR. Optional parameter. PCR event logs are a list (arbitrary length JSON array) of log entries with the following content. - recnum: Unique record number - pcr: PCR index - digest: The digests - type: The type of event. At the moment the only possible value is: "LINUX_IMA" (legacy IMA) - eventDigest: Digest of the event; e.g. the digest of the measured file - eventName: Name of the event; e.g. the name of the measured file. * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--keyPath**=_STRING_: Identifies the signing key. * **-q**, **\--quoteInfo**=_FILENAME_ or _-_ (for stdout): Returns a JSON-encoded structure holding the inputs to the quote operation. This includes the digest value and PCR values. * **-o**, **\--signature**=_FILENAME_ or _-_ (for stdout): Returns the signature over the quoted material. * **-c**, **\--certificate**=_FILENAME_ or _-_ (for stdout): The certificate associated with keyPath in PEM format. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_quote --keyPath=HS/SRK/quotekey --pcrList="10,16" --qualifyingData=qualifyingData.file --signature=signature.file --pcrLog=pcrLog.file --certificate=certificate.file --quoteInfo=quoteInfo.info ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_setappdata.1.md000066400000000000000000000017501412464516500177500ustar00rootroot00000000000000% tss2_setappdata(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_setappdata**(1) # SYNOPSIS **tss2_setappdata** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_setappdata**(1) - This command allows an application to associate an arbitrary data blob with a given object. The data is stored and can be returned with tss2_getappdata. Previously stored data is overwritten by this function. If empty data is passed in, the stored data is deleted. # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: Path of the object for which the appData will be stored. * **-i**, **\--appData**=_FILENAME_ or _-_ (for stdin): The data to be stored. Optional parameter. If omitted, stored data is deleted. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_setappdata --path=HS/SRK/myRSACrypt --appData=appData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_setcertificate.1.md000066400000000000000000000015731412464516500206230ustar00rootroot00000000000000% tss2_setcertificate(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_setcertificate**(1) - # SYNOPSIS **tss2_setcertificate** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_setcertificate**(1) - This command associates an x509 certificate in PEM encoding into the path of a key. # OPTIONS These are the available options: * **-p**, **\--path**=_STRING_: Identifies the entity to be associated with the certificate. * **-i**, **\--x509certData**=_FILENAME_ or _-_ (for stdin): The PEM encoded certificate. Optional parameter. If omitted, then the stored x509 certificate is removed. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_setcertificate --path=HS/SRK/myRSACrypt --x509certData=x509certData.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_setdescription.1.md000066400000000000000000000021731412464516500206610ustar00rootroot00000000000000% tss2_setdescription(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_setdescription**(1) # SYNOPSIS **tss2_setdescription** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_setdescription**(1) - This command allows an application to assign a human readable description to an object in the FAPI metadata store. The stored data can be returned with tss2_getdescription. Previously stored data is overwritten by this function. If an empty description is passed in, the stored data is deleted. # OPTIONS These are the available options: * **-i**, **\--description**=_STRING_: The data to be stored as description for the object. Optional parameter. Previously stored descriptions are overwritten by this function. If omitted any stored description is deleted. * **-p**, **\--path**=_STRING_: The path of the object for which the description will be stored. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_setdescription --path=HS/SRK --description=description ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_sign.1.md000066400000000000000000000030761412464516500165650ustar00rootroot00000000000000% tss2_sign(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_sign**(1) - # SYNOPSIS **tss2_sign** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_sign**(1) - This command uses a key inside the TPM to sign a digest value using the TPM signing schemes as specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-p**, **\--keyPath**=_STRING_: The path to the signing key. * **-s**, **\--padding**=_STRING_: The padding scheme used. Possible values are "RSA_SSA", "RSA_PSS" (case insensitive). Optional parameter. If omitted, the default padding specified in the cryptographic profile (cf., **fapi-profile(5)**) is used. * **-c**, **\--certificate**=_FILENAME_ or _-_ (for stdout): The certificate associated with keyPath in PEM format. Optional parameter. * **-d**, **\--digest**=_FILENAME_ or _-_ (for stdin): The data to be signed, already hashed. * **-f**, **\--force**: Force overwriting the output file. * **-k**, **\--publicKey**=_FILENAME_ or _-_ (for stdout): The public key associated with keyPath in PEM format. Optional parameter. * **-o**, **\--signature**=_FILENAME_ or _-_ (for stdout): Returns the signature in binary form. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_sign --keyPath=HS/SRK/myRSASign --padding="RSA_PSS" --digest=digest.file --signature=signature.file --publicKey=publicKey.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_unseal.1.md000066400000000000000000000016241412464516500171110ustar00rootroot00000000000000% tss2_unseal(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_unseal**(1) - # SYNOPSIS **tss2_unseal** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_unseal**(1) - This command unseals data from a seal in the FAPI metadata store. The used decryption scheme is specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-f**, **\--force**: Force overwriting the output file. * **-p**, **\--path**=_STRING_: Path of the object for which the blobs will be returned. * **-o**, **\--data**=_FILENAME_ or _-_ (for stdout): The decrypted data after unsealing. Optional parameter. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_unseal --path=HS/SRK/myRSACrypt --data=data.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_verifyquote.1.md000066400000000000000000000043471412464516500202110ustar00rootroot00000000000000% tss2_verifyquote(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_verifyquote**(1) - # SYNOPSIS **tss2_verifyquote** [*OPTIONS*] [common fapi references](common/tss2-fapi-references.md) # DESCRIPTION **tss2_verifyquote**(1) - This command verifies that the data returned by a quote is valid. This includes * Reconstructing the quoteInfo's PCR values from the eventLog (if an eventLog was provided) * Verifying the quoteInfo using the signature and the publicKeyPath The used signature verification scheme is specified in the cryptographic profile (cf., **fapi-profile(5)**). An application using tss2_verifyquote() will further have to * Assess the publicKey's trustworthiness * Assess the eventLog entries' trustworthiness # OPTIONS These are the available options: * **-Q**, **\--qualifyingData**=_FILENAME_ or _-_ (for stdin): A nonce provided by the caller to ensure freshness of the signature. Optional parameter. * **-l**, **\--pcrLog**=_FILENAME_ or _-_ (for stdin): Returns the PCR event log for the chosen PCR. Optional parameter. PCR event logs are a list (arbitrary length JSON array) of log entries with the following content. - recnum: Unique record number - pcr: PCR index - digest: The digests - type: The type of event. At the moment the only possible value is: "LINUX_IMA" (legacy IMA) - eventDigest: Digest of the event; e.g. the digest of the measured file - eventName: Name of the event; e.g. the name of the measured file. * **-q**, **\--quoteInfo**=_FILENAME_ or _-_ (for stdin): The JSON-encoded structure holding the inputs to the quote operation. This includes the digest value and PCR values. * **-k**, **\--publicKeyPath**=_STRING_: Identifies the signing key. MAY be a path to the public key hierarchy /ext. * **-i**, **\--signature**=_FILENAME_ or _-_ (for stdin): The signature over the quoted material. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_verifyquote --publicKeyPath="ext/myNewParent" --qualifyingData=qualifyingData.file --quoteInfo=quoteInfo.file --signature=signature.file --pcrLog=pcrLog.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_verifysignature.1.md000066400000000000000000000020101412464516500210360ustar00rootroot00000000000000% tss2_verifysignature(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_verifysignature**(1) - # SYNOPSIS **tss2_verifysignature** [*OPTIONS*] # DESCRIPTION **tss2_verifysignature**(1) - This command verifies a signature using a public key found in the passed key path. The used signature verification scheme is specified in the cryptographic profile (cf., **fapi-profile(5)**). # OPTIONS These are the available options: * **-d**, **\--digest**=_FILENAME_ or _-_ (for stdin): The data that was signed, already hashed according to the cryptographic profile (cf., **fapi-profile(5)**). * **-p**, **\--keyPath**=_STRING_: Path to the verification public key. * **-i**, **\--signature**=_FILENAME_ or _-_ (for stdin): The signature to be verified. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_verifysignature --keyPath=ext/myRSASign --digest=digest.file --signature=signature.file ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/man/tss2_writeauthorizenv.1.md000066400000000000000000000014251412464516500212520ustar00rootroot00000000000000% tss2_writeauthorizenv(1) tpm2-tools | General Commands Manual % % APRIL 2019 # NAME **tss2_writeauthorizenv**(1) - # SYNOPSIS **tss2_writeauthorizenv** [*OPTIONS*] # DESCRIPTION **tss2_writeauthorizenv**(1) - This command writes the digest value of a policy to an NV index such that this policy can be used in other policies containing a corresponding PolicyAuthorizeNv element. # OPTIONS These are the available options: * **-p**, **\--nvPath**=_STRING_: The path of the NV index. * **-P**, **\--policyPath**=_STRING_: The path of the new policy. [common tss2 options](common/tss2-options.md) # EXAMPLE ``` tss2_writeauthorizenv --nvPath=/nv/Owner/myNV --policyPath=/policy/pcr-policy ``` # RETURNS 0 on success or 1 on failure. [footer](common/footer.md) tpm2-tools-5.2/misc/000077500000000000000000000000001412464516500143435ustar00rootroot00000000000000tpm2-tools-5.2/misc/coding_standard_c.md000066400000000000000000000243261412464516500203210ustar00rootroot00000000000000# TPM2.0-tools Coding Standard ## Golden rule * Code should hold as close to the C99 standard as possible with the exception that GCC specific extensions are generally accepted. * The code must compile without warnings (for the primary target compiler) if the compiler is instructed to report all warnings. * If some warning is unavoidable, the offensive line must be documented as to why it can not be changed to remove the warning. * It may also be possible to suppress specific warnings dependent on compiler options [1]– this is acceptable but could also be dangerous if the suppression has too large a scope. ## Commenting There are four acceptable commenting styles: block, critical-line, next-line, and line. 1. Block comments indicate many lines of code below are being covered by the comment. These are useful as file, function, algorithmic, or multi-line equation level comments. ``` /* * This block comment could apply to some function and describe its inner * workings. Notice these sentences have traditional capitalization and * punctuation... that's because it has to be read in a way completely * unlike the Post-It style content of next-line and line comments. */ ``` 2. Next-line comments apply only to the line of code immediately beneath them. ``` /* the next line is regular, but needs a comment */ ``` 3. Critical-line comments are equivalent to next-liners, but they are formatted like block comments to indicate the line of code following (or the comment itself) is more important than normal. ``` /* * This line or comment is important... at least more than usual */ ``` 4. Line comments apply to the line on which they appear, always to the right of all code on the line. Line comments are preferred over next-liners because they do not interrupt the vertical flow of code. ``` // This is also acceptable for a line comment. ``` ``` // This is not an acceptable block comment. // These read very imbalanced. // Don't do this. ``` Note: * Block comments, next-line comments and critical-line comments are formatted so that the initial "/*" is left with the code/ scope to which it applies. * The size of comment should be proportional to the size of the code that it refers to. Consequently, properties of code that can fit within a single 24-line screen should not be commented unless they are not obvious. By contrast, even obvious global properties and invariants may need to be made explicit. This doesn't have to be through comments, though. The assert() macro is an excellent executable comment. [2] * Use the next-line style if the line of code would exceed 80 characters when a line comment is added. Next-line and line comments should be used sparingly since they are rarely complete sentences, it is often better in the long run to rewrite the line of code to be understandable alone or in the context of a block comment. * All source files and functions require leading block comments for consistency. ## Naming conventions 1. Variable names should clearly imply what their values mean. Do not rely on the types of variables to do this. 2. Multiple word names are descriptive and most easily read if words are separated with the underscore character, “_â€. 3. DoNotUseCamelBackStyle because ItIsNotAs easy to read, especially when actual whitespace IsAddedFor syntactical purposes. 4. It is common practice to keep variable and function names completely lowercase. 5. Constants are usually lowercase as well, but some groups prefer the standard of all-caps so they have the “eye feel†of older #define macros. ``` unsigned int table_index = find_index(jacket_table, “colorâ€, COLOR_RED); ``` 7. Single letter variable names should be avoided. Exceptions are: * i, j, k are loop counters or temporary array indexes * m and n are row and column indexes for multidimensional arrays * c and s are temporary/parameter characters or strings * r, g, b, and a are red, green, blue, and alpha levels, but only when they are used together x, y, and z are coordinate values. 8. Abbreviated words in variable names should be avoided. Exceptions are: * char = character * col = column. Typically there is also “row†so it's not confused with color * cnt = count * pos = position * rem = remainder 6. Boolean variables should be named to reflect the true condition... even if the variable is used to detect false conditions. Boolean variables should be declared as type bool using . ``` int last_item = 0; while(!last_item) { /* ... */ } ``` ``` int char_found = is_alpha(c); ``` 9. Function names should follow the naming conventions of variables and clearly imply not only what the function does, but also the nature of what it returns (if anything). 10. Functions that return boolean integers should be named to reflect the true condition. Even if they are created to detect false conditions. ``` bool is_number_prime = is_prime(i); if(is_number_prime) { /* ... */ } ``` 11. Functions should never be hidden in conditional statements, with the exception of loops where it makes the code simpler. ``` while(!labeled_correctly(sample[i])) { /* ... */ } ``` 12. A function that is exported for use in multiple source files should be prefixed with the source file (or object module) name it was defined in (not declared. Infinite declarations are allowed, but only one definition). * For example, the file list.c may contain the implementation of a dynamic list ADT including an exported method for creating a list instance and an internal (static) method for overflow checking. * The first function might be named “list_createâ€, and the second, “is_overflowedâ€. 13. A function used only within its definition source file should be declared static (as should all variables global to only one file's scope), have no prefix, and must not be declared in any header files. 14. A function used externally from its definition source file should be declared extern in the source's associated header file. ## Files 1. Typically, every header file has the same base filename as an associated source file. 2. Each header file is bound by conditional compilation commands using an all caps and underscored variant of the complete filename. 3. Header files should never define functions or variables. ``` /* * File: basic_file.h * Header file block comment */ #ifndef BASIC_FILE_H #define BASIC_FILE_H /* standard #includes */ /* project #includes */ /* type/constant definitions */ /* extern variable declarations */ /* extern function declarations */ #endif /* BASIC_FILE_H */ ``` ``` /* * File: basic_file.c * Source file block comment... */ /* standard #includes */ /* project #includes */ #include “basic_file.h†/* externalized variable definitions */ /* static variables (locally global) */ /* static function declarations */ /* externalized function definitions */ /* static function definitions */ ``` 4. Header files should only #include what is necessary to allow a file that includes it to compile. 5. Associated source files will always #include the header of the same name, but should #include files whose resources are used within the source even if they are already included in that header. This provides a complete context for readers of the source file; i.e. they don't have to search through headers to determine where a resource came from. For example, consider a header and source that use FILE pointers declared in stdio.h. * The header must #include to ensure files that include it will be able to compile. * The corresponding source #includes the associated header and therefore receives the benefit of stdio.h automatically. * The source would be unnerving if the FILE type was used and stdio.h was not #included. ## Variable Scope and types 1. Variables should be declared and scoped to the smallest scope of use. This promotes descriptive variable names as well as dissuading variable re-use when not proper. Also, it promotes a locality, where one can identify the variable and it's corresponding usage in code. ``` /* This should be avoided */ void foo() { unsigned i; do_something(); for(i=0; i < 100; i++) { do_more(i); } } ``` ``` /* Proper variable scope */ void foo() { do_something(); unsigned i; for(i=0; i < 100; i++) { do_more(i); } } ``` 2. Variables should only be of a signed type if something should ever be negative. A common, incorrect use, is to declare loop indices as int instead of unsigned. ## Formatting 1. Always use space characters, 4 spaces per level of indentation. 2. Block statements encapsulated with braces should place the opening brace on the same line after the end of the conditional statement or function parameter list, and the closing brace at the same column position as the beginning of the conditional statement or function return parameter, on the line immediately after the end of the block. ``` if(some_int > 0) { statement1; statement2; } void some_function(arg1, arg2) { statement1; statement2; } ``` 3. Conditional statements (such as if, else, while, for, switch, etc) should always be followed by such block statements, even if they contain only one line statement. These formatting conditions are contrary to Kernighan and Ritchie's “one true brace styleâ€. [3] 4. Line Length should not exceed 80 characters and should be split on the nearest whitespace or delimiter character. ### Formatters Code formatters can found under misc/formatters ## Copyright Statements: 1. Copyright statements will not be included in header files, except under certain conditions. i.e particular blocks of code originated from a different source code base and have differing yet compatible licenses. In this case, that code will be carefully documented. 2. Copyright statements will be permitted in the LICENSE file at the authors discretion. They may choose to update, but it will not be required. ## License Inclusion: All files that can contain an SPDX identifier shall contain an SPDX BSD-3 clause identifier in a single line /* */ statement in the top of the file or closes to top if not possible. ## References 1. Alan Bridger, Mick Brooks, and Jim Pisano, C Coding Standards, 2001, http://www.alma.nrao.edu/development/computing/docs/joint/0009/2001-02-28.pdf 2. Jim Larson, Standards and Style for Coding in ANSI C, 1996, http://www.jetcafe.org/jim/c-style.html 3. Brian Kernighan, Dennis Ritchie, The C Programing Language, 1988 tpm2-tools-5.2/misc/formatters/000077500000000000000000000000001412464516500165315ustar00rootroot00000000000000tpm2-tools-5.2/misc/formatters/tpm2.0-eclipse-cdt-formatter.xml000066400000000000000000000425161412464516500244760ustar00rootroot00000000000000 tpm2-tools-5.2/mkdocs.yml000066400000000000000000000152211412464516500154140ustar00rootroot00000000000000site_name: tpm2-tools docs_dir: doc theme: readthedocs nav: - Home: README.md - INSTALL: INSTALL.md - tpm2: man/tpm2.1.md - tpm2_activatecredential: man/tpm2_activatecredential.1.md - tpm2_certify: man/tpm2_certify.1.md - tpm2_certifycreation: man/tpm2_certifycreation.1.md - tpm2_certifyX509certutil: man/tpm2_certifyX509certutil.1.md - tpm2_changeauth: man/tpm2_changeauth.1.md - tpm2_changeeps: man/tpm2_changeeps.1.md - tpm2_changepps: man/tpm2_changepps.1.md - tpm2_checkquote: man/tpm2_checkquote.1.md - tpm2_clear: man/tpm2_clear.1.md - tpm2_clearcontrol: man/tpm2_clearcontrol.1.md - tpm2_clockrateadjust: man/tpm2_clockrateadjust.1.md - tpm2_commit: man/tpm2_commit.1.md - tpm2_create: man/tpm2_create.1.md - tpm2_createak: man/tpm2_createak.1.md - tpm2_createek: man/tpm2_createek.1.md - tpm2_createpolicy: man/tpm2_createpolicy.1.md - tpm2_createprimary: man/tpm2_createprimary.1.md - tpm2_dictionarylockout: man/tpm2_dictionarylockout.1.md - tpm2_duplicate: man/tpm2_duplicate.1.md - tpm2_ecdhkeygen: man/tpm2_ecdhkeygen.1.md - tpm2_ecdhzgen: man/tpm2_ecdhzgen.1.md - tpm2_ecephemeral: man/tpm2_ecephemeral.1.md - tpm2_encryptdecrypt: man/tpm2_encryptdecrypt.1.md - tpm2_eventlog: man/tpm2_eventlog.1.md - tpm2_evictcontrol: man/tpm2_evictcontrol.1.md - tpm2_flushcontext: man/tpm2_flushcontext.1.md - tpm2_getcap: man/tpm2_getcap.1.md - tpm2_getcommandauditdigest: man/tpm2_getcommandauditdigest.1.md - tpm2_geteccparameters: man/tpm2_geteccparameters.1.md - tpm2_getekcertificate: man/tpm2_getekcertificate.1.md - tpm2_getrandom: man/tpm2_getrandom.1.md - tpm2_getsessionauditdigest: man/tpm2_getsessionauditdigest.1.md - tpm2_gettestresult: man/tpm2_gettestresult.1.md - tpm2_gettime: man/tpm2_gettime.1.md - tpm2_hash: man/tpm2_hash.1.md - tpm2_hierarchycontrol: man/tpm2_hierarchycontrol.1.md - tpm2_hmac: man/tpm2_hmac.1.md - tpm2_import: man/tpm2_import.1.md - tpm2_incrementalselftest: man/tpm2_incrementalselftest.1.md - tpm2_load: man/tpm2_load.1.md - tpm2_loadexternal: man/tpm2_loadexternal.1.md - tpm2_makecredential: man/tpm2_makecredential.1.md - tpm2_nvcertify: man/tpm2_nvcertify.1.md - tpm2_nvdefine: man/tpm2_nvdefine.1.md - tpm2_nvextend: man/tpm2_nvextend.1.md - tpm2_nvincrement: man/tpm2_nvincrement.1.md - tpm2_nvread: man/tpm2_nvread.1.md - tpm2_nvreadlock: man/tpm2_nvreadlock.1.md - tpm2_nvreadpublic: man/tpm2_nvreadpublic.1.md - tpm2_nvsetbits: man/tpm2_nvsetbits.1.md - tpm2_nvundefine: man/tpm2_nvundefine.1.md - tpm2_nvwrite: man/tpm2_nvwrite.1.md - tpm2_nvwritelock: man/tpm2_nvwritelock.1.md - tpm2_pcrallocate: man/tpm2_pcrallocate.1.md - tpm2_pcrevent: man/tpm2_pcrevent.1.md - tpm2_pcrextend: man/tpm2_pcrextend.1.md - tpm2_pcrread: man/tpm2_pcrread.1.md - tpm2_pcrreset: man/tpm2_pcrreset.1.md - tpm2_policyauthorize: man/tpm2_policyauthorize.1.md - tpm2_policyauthorizenv: man/tpm2_policyauthorizenv.1.md - tpm2_policyauthvalue: man/tpm2_policyauthvalue.1.md - tpm2_policycommandcode: man/tpm2_policycommandcode.1.md - tpm2_policycountertimer: man/tpm2_policycountertimer.1.md - tpm2_policycphash: man/tpm2_policycphash.1.md - tpm2_policyduplicationselect: man/tpm2_policyduplicationselect.1.md - tpm2_policylocality: man/tpm2_policylocality.1.md - tpm2_policynamehash: man/tpm2_policynamehash.1.md - tpm2_policynv: man/tpm2_policynv.1.md - tpm2_policynvwritten: man/tpm2_policynvwritten.1.md - tpm2_policyor: man/tpm2_policyor.1.md - tpm2_policypassword: man/tpm2_policypassword.1.md - tpm2_policypcr: man/tpm2_policypcr.1.md - tpm2_policyrestart: man/tpm2_policyrestart.1.md - tpm2_policysecret: man/tpm2_policysecret.1.md - tpm2_policysigned: man/tpm2_policysigned.1.md - tpm2_policytemplate: man/tpm2_policytemplate.1.md - tpm2_policyticket: man/tpm2_policyticket.1.md - tpm2_print: man/tpm2_print.1.md - tpm2_quote: man/tpm2_quote.1.md - tpm2_rc_decode: man/tpm2_rc_decode.1.md - tpm2_readclock: man/tpm2_readclock.1.md - tpm2_readpublic: man/tpm2_readpublic.1.md - tpm2_rsadecrypt: man/tpm2_rsadecrypt.1.md - tpm2_rsaencrypt: man/tpm2_rsaencrypt.1.md - tpm2_selftest: man/tpm2_selftest.1.md - tpm2_send: man/tpm2_send.1.md - tpm2_sessionconfig: man/tpm2_sessionconfig.1.md - tpm2_setclock: man/tpm2_setclock.1.md - tpm2_setcommandauditstatus: man/tpm2_setcommandauditstatus.1.md - tpm2_setprimarypolicy: man/tpm2_setprimarypolicy.1.md - tpm2_shutdown: man/tpm2_shutdown.1.md - tpm2_sign: man/tpm2_sign.1.md - tpm2_startauthsession: man/tpm2_startauthsession.1.md - tpm2_startup: man/tpm2_startup.1.md - tpm2_stirrandom: man/tpm2_stirrandom.1.md - tpm2_testparms: man/tpm2_testparms.1.md - tpm2_unseal: man/tpm2_unseal.1.md - tpm2_verifysignature: man/tpm2_verifysignature.1.md - tpm2_zgen2phase: man/tpm2_zgen2phase.1.md - tss2_authorizepolicy: man/tss2_authorizepolicy.1.md - tss2_changeauth: man/tss2_changeauth.1.md - tss2_createkey: man/tss2_createkey.1.md - tss2_createnv: man/tss2_createnv.1.md - tss2_createseal: man/tss2_createseal.1.md - tss2_decrypt: man/tss2_decrypt.1.md - tss2_delete: man/tss2_delete.1.md - tss2_encrypt: man/tss2_encrypt.1.md - tss2_exportkey: man/tss2_exportkey.1.md - tss2_exportpolicy: man/tss2_exportpolicy.1.md - tss2_getappdata: man/tss2_getappdata.1.md - tss2_getcertificate: man/tss2_getcertificate.1.md - tss2_getdescription: man/tss2_getdescription.1.md - tss2_getinfo: man/tss2_getinfo.1.md - tss2_getplatformcertificates: man/tss2_getplatformcertificates.1.md - tss2_getrandom: man/tss2_getrandom.1.md - tss2_gettpmblobs: man/tss2_gettpmblobs.1.md - tss2_import: man/tss2_import.1.md - tss2_list: man/tss2_list.1.md - tss2_nvextend: man/tss2_nvextend.1.md - tss2_nvincrement: man/tss2_nvincrement.1.md - tss2_nvread: man/tss2_nvread.1.md - tss2_nvsetbits: man/tss2_nvsetbits.1.md - tss2_nvwrite: man/tss2_nvwrite.1.md - tss2_pcrextend: man/tss2_pcrextend.1.md - tss2_pcrread: man/tss2_pcrread.1.md - tss2_provision: man/tss2_provision.1.md - tss2_quote: man/tss2_quote.1.md - tss2_setappdata: man/tss2_setappdata.1.md - tss2_setcertificate: man/tss2_setcertificate.1.md - tss2_setdescription: man/tss2_setdescription.1.md - tss2_sign: man/tss2_sign.1.md - tss2_unseal: man/tss2_unseal.1.md - tss2_verifyquote: man/tss2_verifyquote.1.md - tss2_verifysignature: man/tss2_verifysignature.1.md - tss2_writeauthorizenv: man/tss2_writeauthorizenv.1.md tpm2-tools-5.2/scripts/000077500000000000000000000000001412464516500150775ustar00rootroot00000000000000tpm2-tools-5.2/scripts/utils/000077500000000000000000000000001412464516500162375ustar00rootroot00000000000000tpm2-tools-5.2/scripts/utils/icert2pem.sh000077500000000000000000000012211412464516500204640ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: BSD-3-Clause usage() { cat <&2 exit 1 ;; esac done if [ "$#" -ne 1 ]; then (>&2 echo "Error: expected 1 certificate file parameter, got: $#") exit 1 fi sed 's/-/+/g;s/_/\//g;s/%3D/=/g;s/^{.*certificate":"//g;s/"}$//g;' $1 | base64 --decode | openssl x509 -inform DER -outform PEM exit 0 tpm2-tools-5.2/scripts/utils/icert_ondie_ca.sh000077500000000000000000000020371412464516500215270ustar00rootroot00000000000000#!/bin/sh # SPDX-License-Identifier: BSD-3-Clause usage() { cat <&2 exit 1 ;; esac done if [ "$#" -ne 1 ]; then (>&2 echo "Error: expected 1 certificate file parameter, got: $#") exit 1 fi hlen=4 rlen=0 i=0 offset=0 offset_str="" flen=$(stat --printf="%s" $1) while [ $offset -lt $flen ];do len=$(openssl asn1parse -in $1 -inform DER $offset_str | grep SEQUENCE | \ head -1 | grep -o 'l= [0-9]\{1,\}' | grep -o '[0-9]\{1,\}') rlen=$(expr $hlen + $len) openssl asn1parse -in $1 -inform DER -length $rlen $offset_str -out $i.der \ -noout openssl x509 -in $i.der -out $i.pem -inform DER -outform PEM rm $i.der offset=$(expr $offset + $rlen) offset_str="-offset $offset" i=$(expr $i + 1) done echo "Found $i intermediate certificates" tpm2-tools-5.2/scripts/utils/man_to_bashcompletion.sh000077500000000000000000000123071412464516500231450ustar00rootroot00000000000000#!/bin/bash commands="" generate_bashcompletion() { k=`basename $1 .1.md` commands+="`echo $k |sed 's/tpm2_//g'` " shortop="$(grep -oP '(?<=\* \*\*\-)([a-zA-Z])' $1)" longoptwithshortop="$(grep -oP '(?<=\* \*\*\-[a-zA-Z]\*\*, \*\*\\--)([a-zA-Z\-]+)' $1)" longopwithoutshortop="$(grep -oP '(?<=\* \*\*\\\-\-)([a-zA-Z]{1,})' $1)" echo "# bash completion for $k -*- shell-script -*-" echo \ "_$k() { local auth_methods=(str: hex: file: file:- session: pcr:) local hash_methods=(sha1 sha256 sha384 sha512) local format_methods=(tss plain) local signing_scheme=(rsassa rsapss ecdsa ecdaa sm2 ecshnorr hmac) local key_object=(rsa ecc aes camellia hmac xor keyedhash) local key_attributes=(\| fixedtpm stclear fixedparent \\ sensitivedataorigin userwithauth adminwithpolicy noda \\ encrypteddupplication restricted decrypt sign) local nv_attributes=(\| ppwrite ownerwrite authwrite policywrite \\ policydelete writelocked writeall writedefine write_stclear \\ globallock ppread ownerread authread policyread no_da orderly \\ clear_stclear readlocked written platformcreate read_stclear) local cur prev words cword split _init_completion -s || return case \$prev in -h | --help) COMPREPLY=( \$(compgen -W \"man no-man\" -- \"\$cur\") ) return;; -T | --tcti) COMPREPLY=( \$(compgen -W \"tabrmd mssim device none\" -- \"\$cur\") ) return;;" shortop_ctr=0 longoptwithshortop_ctr=0 for shortop_index in $shortop;do for longoptwithshortop_index in $longoptwithshortop;do if [ $shortop_ctr == $longoptwithshortop_ctr ];then echo " -$shortop_index | --$longoptwithshortop_index)" if [[ "$longoptwithshortop_index" == *"auth"* ]];then echo " COMPREPLY=(\$(compgen -W \"\${auth_methods[*]}\" -- \"\$cur\"))" elif [[ "$shortop_index" == "g" ]];then echo " COMPREPLY=(\$(compgen -W \"\${hash_methods[*]}\" -- \"\$cur\"))" elif [[ "$shortop_index" == "G" ]];then echo " COMPREPLY=(\$(compgen -W \"\${key_object[*]}\" -- \"\$cur\"))" elif [[ "$longoptwithshortop_index" == *"attributes"* && "$k" != "tpm2_nvdefine" ]];then echo " COMPREPLY=(\$(compgen -W \"\${key_attributes[*]}\" -- \"\$cur\"))" elif [[ "$longoptwithshortop_index" == *"attributes"* && "$k" == "tpm2_nvdefine" ]];then echo " COMPREPLY=(\$(compgen -W \"\${nv_attributes[*]}\" -- \"\$cur\"))" elif [[ "$longoptwithshortop_index" == *"format"* && "$k" != "tpm2_verifysignature" ]];then echo " COMPREPLY=(\$(compgen -W \"\${format_methods[*]}\" -- \"\$cur\"))" elif [[ "$longoptwithshortop_index" == *"scheme"* ]];then echo " COMPREPLY=(\$(compgen -W \"\${signing_scheme[*]}\" -- \"\$cur\"))" else echo " _filedir" fi echo " return;;" fi longoptwithshortop_ctr=$((longoptwithshortop_ctr + 1)) done shortop_ctr=$((shortop_ctr + 1)) longoptwithshortop_ctr=0 done echo -n " esac COMPREPLY=(\$(compgen -W \"-h --help -v --version -V --verbose -Q --quiet \\ -Z --enable-erata -T --tcti \\" echo "" echo -n " " for j in $shortop; do echo -n "-$j "; done for j in $longoptwithshortop; do echo -n "--$j "; done for j in $longopwithoutshortop; do echo -n "--$j "; done echo "\" \\" echo -n " " echo "-- \"\$cur\")) } && complete -F _$k $k" echo "# ex: filetype=sh" } generate_bashcompletion_for_tpm2() { echo "_tpm2() { local cur prev words cword split _init_completion -s || return if ((cword == 1)); then COMPREPLY=(\$(compgen -W \"$commands\" -- \"\$cur\")) else tpmcommand=_tpm2_\$prev type \$tpmcommand &>/dev/null && \$tpmcommand if [ \$? == 1 ];then COMPREPLY=(\$(compgen -W \${words[1]} -- \"\$cur\")) fi fi } && complete -F _tpm2 tpm2" } current_dir="$(readlink -e "$(dirname "$0")")" mandir="$(readlink -e "${current_dir}"/../../man)" bashcompletiondir="$(readlink -e "${current_dir}"/../../dist/bash-completion/tpm2-tools)" rm -f $bashcompletiondir/tpm2_completion.bash for man_file in `ls $mandir/tpm2*.1.md` do generate_bashcompletion $man_file >> $bashcompletiondir/tpm2_completion.bash done generate_bashcompletion_for_tpm2 >> $bashcompletiondir/tpm2_completion.bash tpm2-tools-5.2/scripts/utils/tcgRSApub2PemDer.sh000077500000000000000000000006561412464516500216160ustar00rootroot00000000000000#!/bin/bash # SPDX-License-Identifier: BSD-3-Clause echo 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA' | base64 -d > header.bin echo '02 03' | xxd -r -p >mid-header.bin echo '01 00 01' | xxd -r -p >exponent.bin dd if=$1 of=modulus.bin bs=1 count=256 skip=102 cat header.bin modulus.bin mid-header.bin exponent.bin > $1.cer openssl rsa -in $1.cer -inform DER -pubin > $1.pem rm header.bin modulus.bin mid-header.bin exponent.bin tpm2-tools-5.2/test/000077500000000000000000000000001412464516500143675ustar00rootroot00000000000000tpm2-tools-5.2/test/.gitignore000066400000000000000000000004161412464516500163600ustar00rootroot00000000000000# Ignore everything * # But not these files... !.gitignore !README.md !get-capability-tpm-prop-fixed.bin !ek-template-default.bin !event*.bin !*.sh !*.c !*.h # ...even if they are in subdirectories !*/ # But do ignore the generated ECC files integration/fapi/*_ecc.sh tpm2-tools-5.2/test/integration/000077500000000000000000000000001412464516500167125ustar00rootroot00000000000000tpm2-tools-5.2/test/integration/README.md000066400000000000000000000014541412464516500201750ustar00rootroot00000000000000# Testing Framework The command **make check** can be used to run the test scripts. The configure option `--enable-unit` must be specified and the `tpm2-abrmd` and `tpm_server` must be found on `$PATH`. If they are installed in custom locations, specify or export `$PATH` during configure. For example: ```sh ./configure --enable-unit PATH=$PATH:/path/to/tpm2-abrmd:/path/to/tpm/sim/ibmtpm974/src ``` ## Adding a new integration test To add a new test, do: 1. add a script to the `test/integration/tests` directory. 2. `source helpers.sh` in the new script. 3. issue the command `start_up`. 4. Do whatever test you need to do. 5. If you set the `EXIT` handler, call `tpm2 shutdown` in that handler. 6. `make distclean`, re-run `bootstrap` and configure to pick up the new script. 7. Run `make check` again. tpm2-tools-5.2/test/integration/fapi/000077500000000000000000000000001412464516500176315ustar00rootroot00000000000000tpm2-tools-5.2/test/integration/fapi/fapi-authorize-policy.sh000066400000000000000000000101761412464516500244160ustar00rootroot00000000000000 set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE function cleanup { tss2 delete --path=/ shut_down } trap cleanup EXIT KEY_PATH=HS/SRK/mySignKey POLICY_SIGN_KEY_PATH=HS/SRK/myPolicySignKey PCR_POLICY_DATA=$TEMP_DIR/pol_pcr16_0.json AUTHORIZE_POLICY_DATA=$TEMP_DIR/pol_authorize_ref.json POLICY_PCR=policy/pcr-policy POLICY_AUTHORIZE=policy/authorize-policy POLICY_REF=$TEMP_DIR/policy_ref.file SIGNATURE_FILE=$TEMP_DIR/signature.file PUBLIC_KEY_FILE=$TEMP_DIR/public_key.file DIGEST_FILE=$TEMP_DIR/digest.file LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file echo -n 01234567890123456789012345678901 > $DIGEST_FILE echo 'f0f1f2f3f4f5f6f7f8f9' | xxd -r -p > $POLICY_REF tss2 provision tss2 import --path=$POLICY_PCR --importData=$PCR_POLICY_DATA tss2 import --path=$POLICY_AUTHORIZE --importData=$AUTHORIZE_POLICY_DATA echo "tss2 import with EMPTY_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 import with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 createkey --path=$POLICY_SIGN_KEY_PATH --type="noDa, sign" --authValue="" tss2 authorizepolicy --keyPath=$POLICY_SIGN_KEY_PATH --policyPath=$POLICY_PCR \ --policyRef=$POLICY_REF tss2 createkey --path=$KEY_PATH --type="noDa, sign" \ --policyPath=$POLICY_AUTHORIZE --authValue="" if [ "$CRYPTO_PROFILE" = "RSA" ]; then tss2 sign --keyPath=$KEY_PATH --padding="RSA_PSS" --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE else tss2 sign --keyPath=$KEY_PATH --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE fi echo "tss2 sign with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi exit 0 tpm2-tools-5.2/test/integration/fapi/fapi-branch-select.sh000066400000000000000000000044051412464516500236170ustar00rootroot00000000000000 set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE function cleanup { tss2 delete --path=/ shut_down } trap cleanup EXIT KEY_PATH="HS/SRK/mySignKey" POLICY_SIGN_KEY_PATH="HS/SRK/myPolicySignKey" PCR_POLICY_DATA=$TEMP_DIR/pol_pcr16_0.json AUTHORIZE_POLICY_DATA=$TEMP_DIR/pol_authorize_ref.json POLICY_PCR=policy/pcr-policy POLICY_PCR2=policy/pcr-policy2 POLICY_AUTHORIZE=policy/authorize-policy SIGNATURE_FILE=$TEMP_DIR/signature.file PUBLIC_KEY_FILE=$TEMP_DIR/public_key.file DIGEST_FILE=$TEMP_DIR/digest.file echo -n 01234567890123456789012345678901 > $DIGEST_FILE POLICY_REF=$TEMP_DIR/policy_ref.file echo 'f0f1f2f3f4f5f6f7f8f9' | xxd -r -p > $POLICY_REF PADDINGS="RSA_PSS" tss2 provision tss2 import --path=$POLICY_PCR --importData=$PCR_POLICY_DATA tss2 import --path=$POLICY_PCR2 --importData=$PCR_POLICY_DATA tss2 import --path=$POLICY_AUTHORIZE --importData=$AUTHORIZE_POLICY_DATA tss2 createkey --path=$POLICY_SIGN_KEY_PATH --type="noDa, sign" --authValue="" tss2 authorizepolicy --keyPath=$POLICY_SIGN_KEY_PATH --policyPath=$POLICY_PCR \ --policyRef=$POLICY_REF tss2 authorizepolicy --keyPath=$POLICY_SIGN_KEY_PATH --policyPath=$POLICY_PCR2 \ --policyRef=$POLICY_REF tss2 createkey --path=$KEY_PATH --type="noDa, sign" \ --policyPath=$POLICY_AUTHORIZE --authValue="" expect < $PLAIN_TEXT set -x if [ "$CRYPTO_PROFILE" = "ECC" ]; then echo ECC currently not supported for encryption. Skipping test. exit 077 fi tss2 provision expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 encrypt --keyPath=$KEY_PATH --plainText=$PLAIN_TEXT \ --cipherText=$ENCRYPTED_FILE --force expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 decrypt with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 delete --path=$KEY_PATH # Encrypt/Decrypt with password tss2 createkey --path=$KEY_PATH --type="noDa, decrypt" --authValue=abc tss2 encrypt --keyPath=$KEY_PATH --plainText=$PLAIN_TEXT \ --cipherText=$ENCRYPTED_FILE --force echo -n "Fail" > $DECRYPTED_FILE expect <=2.4.2. # Therefore, make the test conditional VERSION="$(tss2 createkey -v | grep -Po 'fapi-version=.*' | grep -Eo '([0-9]+\.{1})+[0-9]' | sed 's/[^0-9]*//g')" if [ $VERSION -ge "242" ]; then tss2 delete --path=$KEY_PATH tss2 createkey --path=$KEY_PATH --authValue=abc fi exit 0 tpm2-tools-5.2/test/integration/fapi/fapi-export-key.sh000066400000000000000000000050401412464516500232100ustar00rootroot00000000000000 set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE function cleanup { tss2 delete --path=/ shut_down } trap cleanup EXIT KEY_PATH="HS/SRK/myRSADecrypt" KEY_PATH_PARENT="HS/SRK/myParent" JSON_POLICY=$TEMP_DIR/pol_duplicate.json DUPLICATE_POLICY=policy/duplicate-policy EXPORTED_KEY=$TEMP_DIR/exportedKey EXPORTED_PARENT_KEY=$TEMP_DIR/exportedParentKey LOADED_KEY="myNewParent" tss2 provision tss2 import --path=$DUPLICATE_POLICY --importData=$JSON_POLICY expect < $DIGEST_FILE tss2 createkey --path=$KEY_PATH --type="noDa, sign" --authValue=$PW1 if [ "$CRYPTO_PROFILE" = "RSA" ]; then expect < $DATA_EXTEND_FILE echo -n 01234567890123456789 > $LOG_DATA tss2 provision tss2 createnv --path=$NV_PATH --type="noDa, pcr" --size=0 --authValue="" tss2 nvextend --nvPath=$NV_PATH --data=$DATA_EXTEND_FILE --logData=$LOG_DATA echo "tss2 nvextend with EMPTY_FILE data" # Expected to succeed tss2 nvextend --nvPath=$NV_PATH --data=$EMPTY_FILE --logData=$LOG_DATA echo "tss2 nvextend with BIG_FILE data" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 nvextend with EMPTY_FILE logData" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 nvextend with BIG_FILE logData" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 nvread --nvPath=$NV_PATH --data=$DATA_READ_FILE --logData=$READ_LOG_DATA if [ ! -f $READ_LOG_DATA ]; then echo "No log data returned" exit 1 fi expect < $DIGEST_FILE tss2 provision tss2 createnv --path=$NV_PATH --type="noDa" --size=34 --authValue="" tss2 import --path=$AUTHORIZE_NV_POLICY --importData=$AUTHORIZE_NV_POLICY_JSON tss2 import --path=$POLICY_PCR --importData=$PCR_POLICY_JSON expect < $DATA_WRITE_FILE tss2 import -i $POLICY_NV_DATA -p $POLICY_NV tss2 createnv -p $NV_PATH -P $POLICY_NV -s 16 --authValue=$PW echo "Write with write policy" expect < $LOG_FILE" expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "1\r" set ret [wait] if {[lindex \$ret 2]} { send_user "Command failed\n" exit 1 } EOF echo "Read with read policy." expect < $LOG_FILE" expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "2\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { set file [open $LOG_FILE r] send_user "Command failed\n" exit 1 } EOF echo "Write with read policy should fail." expect < $LOG_FILE" expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "2\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { send_user "Command failed\n" exit 1 } EOF echo "Read with write policy should fail." expect < $LOG_FILE" expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "1\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] send_user "Command failed\n" exit 1 } EOF tss2 delete --path=$NV_PATH if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi exit 0 tpm2-tools-5.2/test/integration/fapi/fapi-nv-write-read-policy-or2.sh000066400000000000000000000071151412464516500255670ustar00rootroot00000000000000set -e source helpers.sh start_up CRYPTO_PROFILE="ECC" setup_fapi $CRYPTO_PROFILE function cleanup { tss2 delete --path=/ shut_down } trap cleanup EXIT PW=abc NV_PATH=/nv/Owner/myNV DATA_WRITE_FILE=$TEMP_DIR/nv_write_data.file DATA_READ_FILE=$TEMP_DIR/nv_read_data.file POLICY_PWD_NV_DATA=$TEMP_DIR/pol_pwd_nv_read_write.json POLICY_PWD_NV=/policy/pwd_nv_read_write LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE PW=abc tss2 provision echo test > $DATA_WRITE_FILE tss2 import -i $POLICY_PWD_NV_DATA -p $POLICY_PWD_NV tss2 createnv -p $NV_PATH -P $POLICY_PWD_NV -s 16 --authValue=$PW echo "Write without password but policy write." expect < $LOG_FILE" set timout 0 expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "2\r" expect -re { "Your choi.*" { } eof { send_user "The system did not comment selection\n" exit 1 } } expect -re { "Select.*" { } eof { send_user "The system has not asked for password\n" exit 1 } } send "1\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { send_user "Using interactive prompt has failed\n" exit 1 } EOF echo "Write with password policy" expect < $LOG_FILE" set timout 0 expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "1\r" expect -re { "Your choi.*" { } eof { send_user "The system did not comment selection\n" exit 1 } } expect -re { "Authorize.*" { } eof { send_user "The system has not asked for password\n" exit 1 } } send "$PW\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { send_user "Using interactive prompt has failed\n" exit 1 } EOF echo "Read with password policy" expect < $LOG_FILE" set timout 0 expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "1\r" expect -re { "Your choi.*" { } eof { send_user "The system did not comment selection\n" exit 1 } } expect -re { "Authorize.*" { } eof { send_user "The system has not asked for password\n" exit 1 } } send "$PW\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { send_user "Using interactive prompt has failed\n" exit 1 } EOF echo "Write with wrong password should fail" expect < $LOG_FILE" set timout 0 expect -re { "Select a branch.*" { } eof { send_user "The system has not asked for branch selection\n" exit 1 } } send "1\r" expect -re { "Your choi.*" { } eof { send_user "The system did not comment selection\n" exit 1 } } expect -re { "Authorize.*" { } eof { send_user "The system has not asked for password\n" exit 1 } } send "XXXXX\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { send_user "Using interactive prompt has failed\n" exit 1 } EOF tss2 delete --path=$NV_PATH if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi exit 0 tpm2-tools-5.2/test/integration/fapi/fapi-nv-write-read.sh000066400000000000000000000112141412464516500235650ustar00rootroot00000000000000 set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE function cleanup { tss2 delete --path=/ shut_down } trap cleanup EXIT PW=abc NV_PATH=/nv/Owner/myNVwrite DATA_WRITE_FILE=$TEMP_DIR/nv_write_data.file DATA_READ_FILE=$TEMP_DIR/nv_read_data.file EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE tss2 provision echo 1234567890123456789 > $DATA_WRITE_FILE tss2 createnv --path=$NV_PATH --type="noDa" --size=20 --authValue="" tss2 nvwrite --nvPath=$NV_PATH --data=$DATA_WRITE_FILE echo "tss2 nvwrite with EMPTY_FILE" # Expected to succeed tss2 nvwrite --nvPath=$NV_PATH --data=$EMPTY_FILE echo "tss2 nvwrite with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 nvread --nvPath=$NV_PATH --data=$DATA_READ_FILE --force if [ `cat $DATA_READ_FILE` != `cat $DATA_WRITE_FILE` ]; then echo "Test without password: Strings are not equal" exit 99 fi tss2 delete --path=$NV_PATH tss2 createnv --path=$NV_PATH --type="noDa" --size=20 --authValue=$PW expect < $PCR_LOG_FILE_WRITE PCR_LOG_FILE_READ=$TEMP_DIR/pcr_log_read.file PCR_EVENT_DATA=$TEMP_DIR/pcr_event_data.file echo "0,1,2,3,4,5,6,7,8,9" > $PCR_EVENT_DATA EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE tss2 provision tss2 pcrextend --pcr=16 --data=$PCR_EVENT_DATA \ --logData=$PCR_LOG_FILE_WRITE echo "tss2 pcrextend with EMPTY_FILE data" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 pcrextend with BIG_FILE data" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 pcrextend with EMPTY_FILE logData" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1 } { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 pcrextend with BIG_FILE logData" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 pcrread --pcrIndex=16 --pcrValue=$PCR_DIGEST_FILE \ --pcrLog=$PCR_LOG_FILE_READ --force if [ ! -s $PCR_DIGEST_FILE ] || [ ! -s $PCR_LOG_FILE_READ ]; then echo "At least one returned file is empty" exit 1 fi expect < $SIGN_POLICY_DATA_KEY_HINT < $SIGN_POLICY_DATA < $PRIV_KEY_FILE < $DIGEST_FILE tss2 provision tss2 import --path=$POLICY_SIGNED --importData=$SIGN_POLICY_DATA tss2 import --path=$POLICY_SIGNED_KEY_HINT --importData=$SIGN_POLICY_DATA_KEY_HINT tss2 createkey --path $KEY_PATH_1 --type="sign, noda" \ --policyPath $POLICY_SIGNED --authValue "" tss2 createkey --path $KEY_PATH_2 --type="sign, noda" \ --policyPath $POLICY_SIGNED_KEY_HINT --authValue "" OUTPUT_FILE=$TEMP_DIR/data2sign.file expect < $LOG_FILE" expect "Filename for nonce output: " { send "$OUTPUT_FILE\r" expect "Filename for signature input: " { exec openssl dgst -sha1 -sign $PRIV_KEY_FILE -out $SIGNATURE_FILE $OUTPUT_FILE send "$SIGNATURE_FILE\r" exp_continue } } EOF if grep "ERROR" $LOG_FILE > /dev/null then cat $LOG_FILE exit 1 fi expect < $LOG_FILE" expect "Filename for nonce output: " { send "$OUTPUT_FILE\r" expect "Filename for signature input: " { exec openssl dgst -sha1 -sign $PRIV_KEY_FILE -out $SIGNATURE_FILE $OUTPUT_FILE send "$SIGNATURE_FILE\r" exp_continue } } EOF if grep "ERROR" $LOG_FILE > /dev/null then cat $LOG_FILE exit 1 fi echo "sign callback with BIG_FILE" # Expected to fail expect < $LOG_FILE" expect "Filename for nonce output: " { send "$OUTPUT_FILE\r" expect "Filename for signature input: " { exec openssl dgst -sha1 -sign $PRIV_KEY_FILE -out $SIGNATURE_FILE $OUTPUT_FILE send "$BIG_FILE\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] == 0} { send_user "\n[lindex \$ret]\n" send_user "Command not failed as expected\n" exit 1 } } set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] == 0} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "\n[lindex \$ret]\n" send_user "Command has not failed as expected\n" exit 1 } } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "sign callback with EMPTY_FILE" # Expected to fail expect < $LOG_FILE" expect "Filename for nonce output: " { send "$OUTPUT_FILE\r" expect "Filename for signature input: " { exec openssl dgst -sha1 -sign $PRIV_KEY_FILE -out $SIGNATURE_FILE $OUTPUT_FILE send "$EMPTY_FILE\r" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] == 0} { send_user "\n[lindex \$ret]\n" send_user "Command has not failed as expected\n" exit 1 } } set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] == 0} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "\n[lindex \$ret]\n" send_user "Command has not failed as expected\n" exit 1 } } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi exit 0tpm2-tools-5.2/test/integration/fapi/fapi-policy_signed_delegation.sh000066400000000000000000000312011412464516500261220ustar00rootroot00000000000000# In this test a backend issues two policies to a user "A": # 1. A user policy that allows "A" to authorize key usage # 2. An offline delegation policy that allows "A" to delegate his access rights # two user "B" without further interaction with the backend. # set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE # Extract value from JSON file function jsonValue { KEY=$1 num=$2 awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'$KEY'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p } function cleanup { # In case the test is skipped, no key is created and a # failure is expected here. Therefore, we need to pass a successful # execution in any case tss2 delete --path=/ && true shut_down } trap cleanup EXIT # The delegation test needs at least the commit # b843960b6e601a786b469832392dc0a12e13cf34 of TSS to be executed successfully. # This commit will be introduced in version > 3.0.3. Will skip the test if # version is below. if [[ "$(echo $TSS_VERSION | sed 's/[^0-9]*//g')" -le "303" && "$TSS_VERSION" != "master" ]]; then echo "TSS version does not support test" exit 077 fi PATH_REVOCATION="/nv/Owner/ctr" PATH_FEATURE_KEY_SIGN="HS/SRK/signkey" # Backend Policies POLICY_AUTH_BACKEND_PEM="pol_authorize_backend_pem.json" PATH_POL_AUTHORIZE="/policy/pol_authorize" # User Policies POLICY_USER="pol_user.json" PATH_POL_USER="/policy/pol_user" POLICY_TO_BE_SIGNED_USER="pol_to_be_signed_user.json" POLICY_AUTHORIZED_USER="pol_authorized_user.json" PATH_POL_AUTHORIZED_USER="/policy/pol_authorized_user" # Offline Delegation Policy POLICY_OFFLINE_DELEGATION="pol_offline_delegation.json" PATH_POL_OFFLINE_DELEGATION="/policy/pol_offline_delegation" POLICY_TO_BE_SIGNED_OFFLINE_DELEGATION="pol_to_be_signed_offline_delegation.json" POLICY_AUTHORIZED_OFFLINE_DELEGATION="pol_authorized_offline_delegation.json" PATH_POL_AUTHORIZED_OFFLINE_DELEGATION="/policy/pol_authorized_offline_delegation" # Sub Policy POLICY_SUB_POLICY="pol_sub_policy.json" PATH_POL_SUB_POLICY="/policy/pol_sub_policy" POLICY_TO_BE_SIGNED_SUB_POLICY="pol_to_be_signed_sub_policy.json" POLICY_AUTHORIZED_SUB_POLICY="pol_authorized_sub_policy.json" PATH_POL_AUTHORIZED_SUB_POLICY="/policy/pol_authorized_sub_policy" # Data for Authorization TEST_SIGNATURE_FILE=$TEMP_DIR/test_signature.file OUTPUT_FILE=$TEMP_DIR/data2sign.file SIGNATURE_FILE=$TEMP_DIR/signature.file search_string="\"policy\":[" LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file # 0. Create Keys openssl ecparam -name secp256r1 -genkey -noout -out $TEMP_DIR/key_backend_priv.pem openssl ec -in $TEMP_DIR/key_backend_priv.pem -pubout -out $TEMP_DIR/key_backend_pub.pem openssl ecparam -name secp256r1 -genkey -noout -out $TEMP_DIR/key_user_priv.pem openssl ec -in $TEMP_DIR/key_user_priv.pem -pubout -out $TEMP_DIR/key_user_pub.pem openssl ecparam -name secp256r1 -genkey -noout -out $TEMP_DIR/key_delegated_priv.pem openssl ec -in $TEMP_DIR/key_delegated_priv.pem -pubout -out $TEMP_DIR/key_delegated_pub.pem # 1. Create necessary policy templates ## Backend Authorization Policy cat < $TEMP_DIR/$POLICY_AUTH_BACKEND_PEM { "description":"Initial Authorization Policy", "policy":[ { "type": "POLICYAUTHORIZE", "policyRef": [ 0, 2, 3, 4, 5 ], "keyPEM": "`cat $TEMP_DIR/key_backend_pub.pem`" } ] } EOF # USER POLICY cat < $TEMP_DIR/$POLICY_USER { "description": "User Policy", "policy": [ { "type": "NV", "nvPath": "`echo $PATH_REVOCATION`", "operandB": "0000000000000002", "operation": "neq" }, { "type": "CounterTimer", "operandB": "5000", "operation": "signed_lt" }, { "type": "Signed", "keyPEM": "`cat $TEMP_DIR/key_user_pub.pem`", "keyPEMhashAlg": "SHA256" } ] } EOF ## Offline Delegation Policy cat < $TEMP_DIR/$POLICY_OFFLINE_DELEGATION { "description":"Offline Delegation", "policy":[ { "type": "POLICYAUTHORIZE", "policyRef": [ 5, 2, 3, 4, 5 ], "keyPEM": "`cat $TEMP_DIR/key_user_pub.pem`" }, { "type": "NV", "nvPath": "`echo $PATH_REVOCATION`", "operandB": "0000000000000002", "operation": "neq" } ] } EOF ## SUB POLICY (will be signed by user) cat < $TEMP_DIR/$POLICY_SUB_POLICY { "description": "Sub Policy", "policy": [ { "type": "CounterTimer", "operandB": "5000", "operation": "signed_lt" }, { "type": "Signed", "keyPEM": "`cat $TEMP_DIR/key_delegated_pub.pem`", "keyPEMhashAlg": "SHA256" } ] } EOF # 2. Create Setting tss2 provision ## Create feature key with authorize policy tss2 import --path $PATH_POL_AUTHORIZE --importData $TEMP_DIR/$POLICY_AUTH_BACKEND_PEM tss2 createkey --path $PATH_FEATURE_KEY_SIGN --type="sign, noda, 0x81000002" --policyPath $PATH_POL_AUTHORIZE --authValue "" ## Create revocation counter tss2 createnv --path $PATH_REVOCATION --type=counter --authValue "" tss2 nvincrement --nvPath $PATH_REVOCATION # 3. Backend creates User Policy and Offline Delegation Policy ## 3.1 Get digests of policies and sign for authorization ### Sign digest of User Policy with key_backend_priv tss2 import --path $PATH_POL_USER --importData $TEMP_DIR/$POLICY_USER tss2 createkey --path HS/SRK/tmpkey --policyPath $PATH_POL_USER --type="sign, noda" --authValue "" tss2 exportpolicy --path HS/SRK/tmpkey --jsonPolicy $TEMP_DIR/$POLICY_TO_BE_SIGNED_USER -f tss2 delete --path HS/SRK/tmpkey tss2 delete --path $PATH_POL_USER digest_user=`cat $TEMP_DIR/$POLICY_TO_BE_SIGNED_USER | jsonValue "digest" 1` digest_user="$digest_user""0002030405" echo -n $digest_user | \ xxd -r -p | openssl dgst -sha256 -sign $TEMP_DIR/key_backend_priv.pem -hex | \ sed 's/^.* //' > signed_user_policy.sig ### Sign digest of Offline Delegation Policy with key_backend_priv tss2 import --path $PATH_POL_OFFLINE_DELEGATION --importData $TEMP_DIR/$POLICY_OFFLINE_DELEGATION tss2 createkey --path HS/SRK/tmpkey --policyPath $PATH_POL_OFFLINE_DELEGATION --type="sign, noda" --authValue "" tss2 exportpolicy --path HS/SRK/tmpkey --jsonPolicy $TEMP_DIR/$POLICY_TO_BE_SIGNED_OFFLINE_DELEGATION -f tss2 delete --path HS/SRK/tmpkey tss2 delete --path $PATH_POL_OFFLINE_DELEGATION digest_offline_delegation=`cat $TEMP_DIR/$POLICY_TO_BE_SIGNED_OFFLINE_DELEGATION | jsonValue "digest" 1` digest_offline_delegation="$digest_offline_delegation""0002030405" echo -n $digest_offline_delegation | \ xxd -r -p | openssl dgst -sha256 -sign $TEMP_DIR/key_backend_priv.pem -hex | \ sed 's/^.* //' > signed_policy_offline_delegation.sig ### Sign digest of Sub Policy with key_user_priv tss2 import --path $PATH_POL_SUB_POLICY --importData $TEMP_DIR/$POLICY_SUB_POLICY tss2 createkey --path HS/SRK/tmpkey --policyPath $PATH_POL_SUB_POLICY --type="sign, noda" --authValue "" tss2 exportpolicy --path HS/SRK/tmpkey --jsonPolicy $TEMP_DIR/$POLICY_TO_BE_SIGNED_SUB_POLICY -f tss2 delete --path HS/SRK/tmpkey tss2 delete --path $PATH_POL_SUB_POLICY digest_sub_policy=`cat $TEMP_DIR/$POLICY_TO_BE_SIGNED_SUB_POLICY | jsonValue "digest" 1` digest_sub_policy="$digest_sub_policy""0502030405" echo -n $digest_sub_policy | \ xxd -r -p | openssl dgst -sha256 -sign $TEMP_DIR/key_user_priv.pem -hex | \ sed 's/^.* //' > signed_policy_sub_policy.sig ## 3.2 Create Authorized Policies from Template ### Create Authorized User Policy POLICY_AUTH_TEMPLATE_USER=$(cat < $TEMP_DIR/$POLICY_AUTHORIZED_USER ### Create Offline Delegation und Sub Policy POLICY_AUTH_TEMPLATE_OFFLINE_DELEGATION=$(cat < $TEMP_DIR/$POLICY_AUTHORIZED_OFFLINE_DELEGATION POLICY_AUTH_TEMPLATE_SUB_POLICY=$(cat < $TEMP_DIR/$POLICY_AUTHORIZED_SUB_POLICY ## 4. Authorize with authorized policies ### Create some digest data to sign DIGEST_FILE=$TEMP_DIR/digest.file echo -n 01234567890123456789 > $DIGEST_FILE ### Import the authorized policies tss2 import --path $PATH_POL_AUTHORIZED_USER --importData $TEMP_DIR/$POLICY_AUTHORIZED_USER tss2 import --path $PATH_POL_AUTHORIZED_OFFLINE_DELEGATION --importData $TEMP_DIR/$POLICY_AUTHORIZED_OFFLINE_DELEGATION tss2 import --path $PATH_POL_AUTHORIZED_SUB_POLICY --importData $TEMP_DIR/$POLICY_AUTHORIZED_SUB_POLICY ## 4.1 User authorizes key usage with the user policy echo "1. User authorizes key usage with the user policy" expect -c " spawn tss2 sign --keyPath=$PATH_FEATURE_KEY_SIGN --digest=$DIGEST_FILE --signature=$TEST_SIGNATURE_FILE -f expect -re \"Select a branch for P_RSA2048SHA256/HS/SRK/signkey .* Your choice:\" { set branches [split \$expect_out(buffer) \"\n\"] set lstSize [llength \$branches] set index 0 foreach branch \$branches { if {[regexp -nocase \"/policy/pol_authorized_user\" \$branch]} { send \"\$index\r\" break } incr index } if {\$index >= \$lstSize} { send_user \"\nError: Branch @ index \$index not found\n\" exit 1 } expect \"Filename for nonce output: \" { send \"$OUTPUT_FILE\r\" expect \"Filename for signature input: \" { exec openssl dgst -sha256 -sign $TEMP_DIR/key_user_priv.pem -out $SIGNATURE_FILE $OUTPUT_FILE send \"$SIGNATURE_FILE\r\" send_user \"\n\" } } set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { send_user \"\n[lindex \$ret]\n\" send_user \"Command failed\n\" exit 1 } } " ## 4.2 Delegated User authorizes key usage with the offline delegation policy echo "2. Delegated User authorizes key usage with the offline delegation policy" expect -c " spawn tss2 sign --keyPath=$PATH_FEATURE_KEY_SIGN --digest=$DIGEST_FILE --signature=$TEST_SIGNATURE_FILE -f expect -re \"Select a branch for P_RSA2048SHA256/HS/SRK/signkey .* Your choice:\" { set branches [split \$expect_out(buffer) \"\n\"] set lstSize [llength \$branches] set index 0 foreach branch \$branches { if {[regexp -nocase \"/policy/pol_authorized_offline_delegation\" \$branch]} { send \"\$index\r\" break } incr index } if {\$index >= \$lstSize} { send_user \"\nError: Branch @ index \$index not found\n\" exit 1 } expect \"Filename for nonce output: \" { send \"$OUTPUT_FILE\r\" expect \"Filename for signature input: \" { exec openssl dgst -sha256 -sign $TEMP_DIR/key_delegated_priv.pem -out $SIGNATURE_FILE $OUTPUT_FILE send \"$SIGNATURE_FILE\r\" send_user \"\n\" } } set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 0} { send_user \"\n[lindex \$ret]\n\" send_user \"Command failed 2\n\" exit 1 } } " exit 0tpm2-tools-5.2/test/integration/fapi/fapi-provision.sh000066400000000000000000000013571412464516500231400ustar00rootroot00000000000000 set -e source helpers.sh start_up CRYPTO_PROFILE="RSA" setup_fapi $CRYPTO_PROFILE function cleanup { # Since clean up should already been done during normal run of the test, a # failure is expected here. Therefore, we need to pass a successful # execution in any case tss2 delete --path=/ || true shut_down } trap cleanup EXIT tss2 provision PROFILE_NAME=$( tss2 list --searchPath=/ --pathList=- | cut -d "/" -f2 ) tss2 delete --path=/ expect < $NONCE_FILE printf "01234567890123456789" > $PCR_LOG EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE tss2 provision tss2 createkey --path=$KEY_PATH --type="noDa, restricted, sign" --authValue="" tss2 quote --keyPath=$KEY_PATH --pcrList="11, 12, 13, 14, 15, 16" --qualifyingData=$NONCE_FILE \ --signature=$SIGNATURE_FILE --pcrLog=$PCR_LOG \ --certificate=$CERTIFICATE_FILE --quoteInfo=$QUOTE_INFO --force echo "tss2 quote with EMPTY_FILE" # Expected to succeed tss2 quote --keyPath=$KEY_PATH --pcrList="11, 12, 13, 14, 15, 16" \ --qualifyingData=$EMPTY_FILE --signature=$SIGNATURE_FILE --pcrLog=$PCR_LOG \ --certificate=$CERTIFICATE_FILE --quoteInfo=$QUOTE_INFO --force echo "tss2 quote with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 exportkey --pathOfKeyToDuplicate=$KEY_PATH --exportedData=$PUBLIC_QUOTE_KEY --force tss2 import --path="ext/myNewParent" --importData=$PUBLIC_QUOTE_KEY tss2 verifyquote --publicKeyPath="ext/myNewParent" \ --qualifyingData=$NONCE_FILE --quoteInfo=$QUOTE_INFO \ --signature=$SIGNATURE_FILE --pcrLog=$PCR_LOG echo "tss2 verifyquote with EMPTY_FILE qualifyingData" # Expected to succeed tss2 verifyquote --publicKeyPath="ext/myNewParent" \ --qualifyingData=$EMPTY_FILE --quoteInfo=$QUOTE_INFO \ --signature=$SIGNATURE_FILE --pcrLog=$PCR_LOG echo "tss2 verifyquote with BIG_FILE qualifyingData" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with EMPTY_FILE signature" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with BIG_FILE signature" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with EMPTY_FILE quoteInfo" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with BIG_FILE quoteInfo" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with EMPTY_FILE pcrLog" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifyquote with BIG_FILE pcrLog" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi expect < $SEALED_DATA_FILE UNSEALED_DATA_FILE=$TEMP_DIR/unsealed-data.file PCR_POLICY_DATA=$TEMP_DIR/pol_pcr16_0.json POLICY_PCR=policy/pcr-policy COUNT_FILE=$TEMP_DIR/count.file EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file LOG_FILE=$TEMP_DIR/log.file touch $LOG_FILE tss2 provision expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 createseal with BIG_FILE" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi tss2 createseal --path=$KEY_PATH --policyPath=$POLICY_PCR --type="noDa" \ --data=$SEALED_DATA_FILE --authValue="" tss2 unseal --path=$KEY_PATH --data=$UNSEALED_DATA_FILE --force if [ "`xxd $UNSEALED_DATA_FILE`" != "`xxd $SEALED_DATA_FILE`" ]; then echo "Seal/Unseal failed" exit 1 fi tss2 delete --path=$KEY_PATH printf "$SEAL_DATA" | tss2 createseal --path=$KEY_PATH --policyPath=$POLICY_PCR --type="noDa" \ --data=- --authValue="" UNSEALED_DATA=$(tss2 unseal --path=$KEY_PATH --data=- | xxd) V1=$(printf "$SEAL_DATA" | xxd) V2=$UNSEALED_DATA if [ "$V1" != "$V2" ]; then echo "Seal/Unseal failed" exit 1 fi expect < $UNSEALED_DATA_FILE expect < $COUNT_FILE if [ "$(< $COUNT_FILE)" != "15" ]; then echo "Wrong size" exit 99 fi printf "" > $SEALED_DATA_FILE expect < $APP_DATA_SET EMPTY_FILE=$TEMP_DIR/empty.file BIG_FILE=$TEMP_DIR/big_file.file tss2 provision tss2 createkey --path=$KEY_PATH --type="noDa, restricted, decrypt" \ --authValue="" echo "tss2 setappdata with EMPTY_FILE" # Expected to succeed tss2 setappdata --path=$KEY_PATH --appData=$EMPTY_FILE echo "tss2 setappdata with BIG_FILE" # Expected to succeed tss2 setappdata --path=$KEY_PATH --appData=$BIG_FILE tss2 setappdata --path=$KEY_PATH --appData=$APP_DATA_SET tss2 getappdata --path=$KEY_PATH --appData=$APP_DATA_FILE --force if [ "$(< $APP_DATA_FILE)" != "$(< $APP_DATA_SET)" ]; then echo "Files are not equal" exit 99 fi echo -n "" > $APP_DATA_FILE tss2 setappdata --path $KEY_PATH tss2 getappdata --path $KEY_PATH --appData $APP_DATA_FILE --force if [ "$(< $APP_DATA_FILE)" != "" ]; then echo "File not empty" exit 99 fi echo -n "123" | tss2 setappdata --path $KEY_PATH --appData - tss2 getappdata --path $KEY_PATH --appData $APP_DATA_FILE --force if [ "$(< $APP_DATA_FILE)" != "123" ]; then echo "Files are not equal" exit 99 fi expect < $WRITE_CERTIFICATE_FILE < $DIGEST_FILE tss2 createkey --path=$KEY_PATH --type="noDa, sign" --authValue="" if [ "$CRYPTO_PROFILE" = "RSA" ]; then echo -n `cat $DIGEST_FILE` | tss2 sign --digest=- --keyPath=$KEY_PATH \ --padding="RSA_PSS" --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE else echo -n `cat $DIGEST_FILE` | tss2 sign --digest=- --keyPath=$KEY_PATH \ --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE fi tss2 import --path=$IMPORTED_KEY_NAME --importData=$PUBLIC_KEY_FILE tss2 verifysignature --keyPath=$PUB_KEY_DIR/$IMPORTED_KEY_NAME \ --digest=$DIGEST_FILE --signature=$SIGNATURE_FILE echo "tss2 verifysignature with EMPTY_FILE digest" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifysignature with BIG_FILE digest" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifysignature with EMPTY_FILE signature" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi echo "tss2 verifysignature with BIG_FILE signature" # Expected to fail expect < $LOG_FILE" set ret [wait] if {[lindex \$ret 2] || [lindex \$ret 3] != 1} { set file [open $LOG_FILE r] set log [read \$file] close $file send_user "[lindex \$log]\n" exit 1 } EOF if [[ "`cat $LOG_FILE`" == $SANITIZER_FILTER ]]; then echo "Error: AddressSanitizer triggered." cat $LOG_FILE exit 1 fi # Try without certificate if [ "$CRYPTO_PROFILE" = "RSA" ]; then tss2 sign --keyPath=$KEY_PATH --padding="RSA_PSS" --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE --force else tss2 sign --keyPath=$KEY_PATH --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --publicKey=$PUBLIC_KEY_FILE --force fi # Try without public key if [ "$CRYPTO_PROFILE" = "RSA" ]; then tss2 sign --keyPath=$KEY_PATH --padding="RSA_PSS" --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --force else tss2 sign --keyPath=$KEY_PATH --digest=$DIGEST_FILE \ --signature=$SIGNATURE_FILE --force fi if [ "$CRYPTO_PROFILE" = "RSA" ]; then expect < $PLAIN_TEXT expect < $VERSION_FILE VERSION=$(cat $VERSION_FILE | cut -d'=' -f 4) size=${#VERSION} if [ $size -ge 129 ]; then echo "Error: Version length greater than 128 characters" ; exit 1 fi exit 0 tpm2-tools-5.2/test/integration/fixtures/000077500000000000000000000000001412464516500205635ustar00rootroot00000000000000tpm2-tools-5.2/test/integration/fixtures/ek-template-default.bin000066400000000000000000000004721412464516500251120ustar00rootroot00000000000000 ² ƒq—gD„³øÌF¥×$ýR×nR dò¡Ú3iª€Ctpm2-tools-5.2/test/integration/fixtures/event-arch-linux.bin000066400000000000000000000363331412464516500244560ustar00rootroot00000000000000%Spec ID Event03 Ä/í­&‚ËùxAÃDç®3 Ôr @ C‚¸V€ù ?kꊴ}(=³+n«í»ñUûkT U@¤­Nô¿¸:kOpÌ앥•ôfQ[3¨$˜ Ïýßp,Ëd¹XÍÒ¥{º(“{Ÿ{¿ÀxY‘’©ÿ5€/ *?U9‹ Ž Bh‰´Ë[# Μㆵ. Ÿ0å Ö-kVþOóåfu%âùÂcß4aßä‹Ê“Òª à˜+Œ SecureBoot€Çª+˜6p°Ú1„Ö©y{ð ZˆWɸK¡m–÷8Ø x×)ÝË¿7AIˆ£4·¦gf¯`aßä‹Ê“Òª à˜+Œ<PK¡YÀ¥ä”§J‡µ«\+ðr< ‘ù‹ý8¼NŽ1{Ûë¾  0‚ 0‚ô  §{2¡Y‚¤0  *†H†÷  010U Joe Richey (PK)0  180923013156Z21180830013156Z010U Joe Richey (PK)0‚"0  *†H†÷ ‚0‚ ‚¹Q_C‡…±T,òáà¬Ër]'»»ó&5 ~ÿà´yŒØà=~çÿð_Û,÷DS‰l‘)!¦]OÖÕ F\X‘B `ͰÑ{«rxà!a  –ÊB%‚^1g®…Ëý/"EÌBë¼Û@²ä¢c'H}•¢1Ù©TÝËÜÎ;mOåNèÿ_àòÄ0Â6¼šUØ€Óòçþk ð•ìRPX¡ìÇ·?Úó(`³Ñɧzqaàé ®¥¶sØZM&(ž&Î5ú{Â2ð¦0¼äÅׯÄ,ßXÁQ¥Kµ ³› F1}&‘t wCYŸ/îu¸,c·#²|"•_Þd#£S0Q0U¸ÃùLðö×M(kÞp¼¶Öü‰  0U#0€¸ÃùLðö×M(kÞp¼¶Öü‰  0Uÿ0ÿ0  *†H†÷  ‚–Ì&#ñöʃìÁùxiÔßBwú+;!E{¤ÓìÀ‹v ä¼ñ"ê»JIñ”¿k.‚Ú×Qº3I¶í….k‡!èIeÜÂúd‡ˆ1à,G8Š:bG·¶™^I™2*hcëxöýžÆàA¼“9xCÏ»Éôï0Ý*ŒB¬§ ßœŠñXwŠ'­>Á ÉÓU ˆþW í¸3{5É‹õ|¯šƒýÒÏ•¥"1I¬JÛÈ­&c#aë ·/r3Ñú‡¬øQP•®aú80ai‘e_ÕÒÀøµ/˜êÿ¨={N¢ÝJ+Eós³L ’aDÂg(T"ç‰ÑË Š€Ró‹Y%49\ýÌøªüÌ,ì]) 0`¹mYà¿M‚2ûÌÃý!›ôVTÅ›âæ“SÛ| aßä‹Ê“Òª à˜+ŒV KEK¡YÀ¥ä”§J‡µ«\+ðr>"‘ù‹ý8¼NŽ1{Ûë¾  0‚0‚ö  ¾½G’0  *†H†÷  010U Joe Richey (KEK)0  180923013219Z21180830013219Z010U Joe Richey (KEK)0‚"0  *†H†÷ ‚0‚ ‚«<¢‡\òÕb¥¢Ql}ö½ Ô²[¹]ù*Ôÿe{ãØl,ãÒ¯Tœµ¼[ù?hkçb#õi}ÁLt¾¨PeiMZRñCµ‹aÜóduÏññ©Ù`I¼Í„ñ Š¬Þ¼[Š : zð›@Ùë›yC_‘Bñgéµ”¢2ôÜ›:+|üD_“ïJ¥¥D§uÃFy´ÊŽ1ýv§9.;η›„«è3Ù%†IÿËHbwTÏ|Nx¨éûHÜÅx7À‚ïØŸÅaó¾ûÓbªwKáúnbyCOqì=D%Óø¤ÌÂýË<§Ìx¬âcÄÅdE ¡¨šK‹-ë—Þdn:‚Щ©£S0Q0Uûù˜ø–'k½O )D"üsü0U#0€ûù˜ø–'k½O )D"üsü0Uÿ0ÿ0  *†H†÷  ‚¤ÕaÙ¶T§~ W//Ï ø–‘ÃÓ4/LRy®äR88ì!Qfé8©ñ•6 ûp±±‘‡ÐÇ!jFbRéíˆYÇÿÁo¦Ñ®ÿ=ü½ý3yÀƒõùrAÐÃÌ—¨ºÕ¯bÁ×R?-bx‰¢ ûoѱZ¸ ½ºS¼Ü-ƒ|A> ¬{£»FûõÔf59%" 1ÇêÚ¶o«¶"O9ÎWö¡Ômm44|ÖéN ôP5ªFLÅlP¤O5Û¼îí± Ægí¢:ók=åGVY“J"뺵…Q ,´ƒ¢ýÈ¡²îd@‘WaÜKÕí’0²·z¯.ìQ8£8~Ï<ãBD¡¡YÀ¥ä”§J‡µ«\+ðrü½šúwY2M½`(ôçxK0‚è0‚Р a ш0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110624204129Z 260624205129Z0€1 0 UUS10U Washington10URedmond10U Microsoft Corporation1*0(U!Microsoft Corporation KEK CA 20110‚"0  *†H†÷ ‚0‚ ‚Ä赊¿­W&°&ÃêçûWzD] ÚJåt*æ°ìmëì¹ãZc2|Oã §8“ŽÆõà„±š›,çõ·‘Ö áâÀ¨¬0ßHóPšd§QÈ…O †Îþ/áŸÿ‚ÀíéÍÎôSjb: C¹â%ýþùÔÄ«â#‰p·¤Mì®åœúÂ×ÁËÔèÄ/å™î$‹ìò‹êÃJûC ~µG’lÜæ‰ëõ3ë*qåùƒ<ÿ% /hvFÿºO¾Ü­q*XªûÒy=ä›e;Ì)*ŸürY¢ë®’ïö5€Æìä_ÌvÍïc’Á¯y@„y‡ãR¨è{i£‚O0‚K0 +‚70UbüCÍ >¤ËgÒ[ÙU¬{̶Š_0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚Ô„ˆõ”Ê*<û*’ × ÑñèRf¨î¢µuzª-¤vZêy·¹7jQ{döádòg¾÷¨x½ºÎˆXd ÖWÈ£_ÖÛÆÐiÎHK2·ë]Ò0õÀõ¸ºx£+þ›Û4V„ì‚Ê®A%pœkéþ×–å甲* Kÿ(){÷×|¥Ñv¹Èyí’œÂþßo~l{ÔÁEÝ4Q–9å^VØ–ô¦B³ wýòqVÌŸ†#¤‡Ë¦ýX~Ôig‘~òå ‹Š<‡„ëãνCå­-„“Žj+Z|DúRªÈ-»àRßøš=Á`°á3µ£ˆÑe ç¬|¤Á‚‡N8±/ Ňoý.¼9¶çæÃàäÍ'„ï”Bï)‹FA;gØùCYeË ¼ý’Oôu;§©$üPA@yà-O j'vnRí–i{¯÷‡ÐE­Sû0ª76aÚJi4ØhíÖÏl” ÓÏl"y­±ð¼¢F`©ÄÂ!‚ñýòèy2`¿Ø¬¥"KÊÁØKë}?W5²æOu´°`"S®‘yÖ›A†Tp²Þ 5|°4rº—`;ðy뢲]¢¸‡Åéöµ—%o8Ÿã‘úŠy˜Ãi·£ —øÊ®×ÄóÀuk4 µ™`ó\°ÅWN6Ò2„¿ž€è]ñì¦c}$%›éÍÅǹ!ÂMÌ Û³æòîf„嵟RßURj?-ÇNßÓ»=ꔿݥS˲×:=–E£¼ÚÐgeo/db¡YÀ¥ä”§J‡µ«\+ðr< ‘ù‹ý8¼NŽ1{Ûë¾  0‚ 0‚ô  Ø¿†Ŧì0  *†H†÷  010U Joe Richey (DB)0  180923013231Z21180830013231Z010U Joe Richey (DB)0‚"0  *†H†÷ ‚0‚ ‚ G`Ù ™‹ŠêT&]3 c·g-7Òp–ô}–f³L¦_©hÀ¤Q:êb¶Åð?v|÷`«QšµßÕƒp8÷J§â¿½\ ¤Vf5:©úŽ NÎÿîÝašŒïèøSó`«^3k‰ŸUϼƒ{I艧˜åW˜¿P|Dr„»¨Js@×?IãÙFÜÅ…™ê}9‚µâ2Â~xË”ŽÉ5$ƒ-‡¥Y3s¤H¢Vþ¿ëvªü N'ìý.iܲ¾€ÞâmI=ý‡^Åe ]Y¸Ùõ¤O@ÝÁ·¨³FÊ’! I&^øë9S"¾† œMPÀ÷"[vµth /£S0Q0Uň”4#AÌý=Ø!ó#0ÒK_0U#0€Åˆ”4#AÌý=Ø!ó#0ÒK_0Uÿ0ÿ0  *†H†÷  ‚,Á´xC7ˆ„fnESý@¹º“¶/ÏQ¥>zü!ÌÚn=w’-…'¬™°¹—f’_7é57ç3þðÎ|ý òcƒéSIи): w¨Œƒ ¤WÔcÛî2ƒŠùQµù¼"¼þxHìØ"Ÿëãe’¥÷M¢@û -–@ÏLlˆþõœ?[)„îëŸðÖ‡÷°Žãkbr«+ú¥'¤uè§(órswIQ=óã±aר6j攕ÜäŽå4nÁ“r~Aýõc¯?©ê¿ùÇ¢ó1<ŽSáɰ—ãžõç%}"]ÁײՑMó,ÕèxæJw'ì6±¡YÀ¥ä”§J‡µ«\+ðr뽚úwY2M½`(ôçxK0‚×0‚¿  avV0  *†H†÷  0ˆ1 0 UUS10U Washington10URedmond10U Microsoft Corporation1200U)Microsoft Root Certificate Authority 20100 111019184142Z 261019185142Z0„1 0 UUS10U Washington10URedmond10U Microsoft Corporation1.0,U%Microsoft Windows Production PCA 20110‚"0  *†H†÷ ‚0‚ ‚Ý »¢ä. ãçÅ÷–i¼!½i33ï­ËT€îƒ»Å „Ù÷Ò‹ó8°«¤­-|byÿãJ?5 pãÄçkàœÀ6uéŠ1ÝpåÜ7µtF–([‡`#,¿ÜG¥g÷Q'žrë¦É¹;S5|åÓì'¹‡þ¹É# o¨F‘Án–http://www.microsoft.com/pki/certs/MicRooCerAut_2010-06-23.crt0  *†H†÷  ‚ü|qQ¥yÂn²ï9>¼«\`ìß¨Ó éôö–…¶QˆfG¢°=*hw»‘Lb{¶ÁǺz‡4Kbz™éÊüÎJ7É-¤W|þ=ܸZúÖij…:ê³Ùnäi!7ÞÑöugÓ“W^)9Èî-áÍäEs[ÐÒÎz«‚FXÐ^³g¯l5ò¼å?$â5¢ uöV™Ôx,ÑëЈªñߺ~,c·›#!ÄùxlâX6+‘̤Ùò-ºù”@íEñΊ\k>«Óp* jà_GÑÕc 2ò¯×6*pZåBYqKWº~ƒð!<ôÁŹ“ˆE“†é± ™¾˜ËÅ•¤]bÖ c ½uw}=óE¹Ÿ—ŸËW€o3©Ïw¤bY~¡YÀ¥ä”§J‡µ«\+ðr@$½šúwY2M½`(ôçxK0‚0‚ø  aÓÄ0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110627212245Z 260627213245Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U"Microsoft Corporation UEFI CA 20110‚"0  *†H†÷ ‚0‚ ‚¥lLÇE jK ¤À‡u CTdàí’} ²s¿ ÆJEa Å-–Óõ+ ûMI›A€<¹Týæ¼ÑĤŠAŠ\Yƒh2»ŒGÉîq¼!OšŠ|ÿD?2²&H®uµîÉLJ~䂚xwM °½öÓÓ¼ú+¥Q8]õûºÛxÛÿì –Õƒ¸é¶À{@{á('ÉúïV^æ~”~ÀðD²y9åÚ²b‹M¿8pâh$É3¤7ÕXi^Ó|íÁSçN°*‡caocYê²+y× agŠ[ý^­‡º†gOqX"""΋ïTqÎP5Xv•îj±¢Õ£‚v0‚r0 +‚70# +‚7øÁk·wSJó%7N¡&{ p€0U­¿C ½‚pœŒÕO1nÕ"˜ŠÔ0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚5Bÿ0ÌÎ÷v ­hX5)F2v'|ïA'BJªm8HYUóéX4¦ ‚ª]­‚Ú€ƒA´ò¹ó]ñPù³U„B( ½²®QÅÀ¬—•!Ûüwž•s‘ˆÊ½½R¹P ßWž aí åm%Ù@@ÈΣJÂM¯šT½Ç¼¹+=I+2üj!iO›È~B4ü6‹ @À³š%u'ÍÉ£ö]Ñç6Tz¹PµÓÑ¿»tßÜ€Õíô/k/ÞfŒ°#åÇ„ØíêÁ3‚­VK-ñh•ÍÏðrð®»Ý†…˜,!L3+ðJðh‡µ’U2u¡j‚j<£%¤í­×®ËØ@Y „Ñ•Lb‘"tŒ=GD¦ä°›45±ú¶S¨,ì¤qȸºèDfäGTŽV³Ÿ˜²†Ðh>#µ/^P…Æ‚_A¡ô. à™Òluä¶iµ!†úÑöâMÑÚ­,wS%27ÇlRr•†°ñ5ajõ²;PV¦2-þ¢‰ùB†'U¡‚ÊZ›ø0˜T¦G–%/È&äA”\?å–ã…[<>?»GrUâ%"±Ù{ç*£÷Fà Ö‰ã5'bq¦ïÐ'  Y7`ø8”¸àxpøºL†‡”öà®Eîe¶£~iu’›õ¦¼YƒX&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^%QQ:Ól ¸Œp¬ÁXøB…EŸ%ìsšìèÀÑžå*&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^¤ ~“ZPtP¦ÖQî—˜zISJ--³åãÑ[?ª!&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^O¥k¶qÉõ ˆ‡¾Õ¥Áœ.|̾ë>¸•Zì&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^ƒ`‹fH' |•a.±a¤“Y´ä5\Ó¡úÐÀ eÝM&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^›rÝÑ_ Z}ÜÐ !F9¹8Š÷A{&ꓚ„Ã=&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^'Ê’M|9rh)š¾]µ!wsD»ÜÄÆ›X䵡1Æ&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^ß}tòãòƒi¿)3¾QÚÐîŒÊ˜~qÞiîLd*&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^Hyè*±“sz!*LSýªÕ`¨ däæÔeÀ¸Æ%Lƒ&ÄÁLP’@¬©Aù6“C(L0QHÜ&_áJšûøƒ»³^I> ¾3VÇ6´Z q8¶…J¾ƒ¸Ò?(c˜“Þ€ž¶ƒ±­çBpÜ`ƒÝqjÌc£3  D´ÎJMÊšóÈ—ÜVî'Ã…ëˆ÷Ϲ +‚e[²˲×:=–E£¼ÚÐgeoŒdbx&ÄÁLP’@¬©Aù6“C(Œ0½šúwY2M½`(ôçxK€´Ùi1¿ ý‘¦ÑO¤Ræm²@Œ¨`MA’eŸ ½šúwY2M½`(ôçxKõ/ƒ£úœûÖ’r($ÛäE4Ò[…$k;•}¬nÎz½šúwY2M½`(ôçxKÅÙØ¡†âÈ- ¯ª*o.s‡ >d÷,Nïgyj„½½šúwY2M½`(ôçxK63„ÑM. xbd„ÄY­W£ïC–&`HÐXÅ¡›¿v½šúwY2M½`(ôçxK세Kle¥ ©¾q–R0! bÖÓ h2Û²Ò à'%'ß¶=IÒ•r¦ôL½šúwY2M½`(ôçxK^ê‰T‹ `²þíÚ< Çþ›Ík”覃¸R8½šúwY2M½`(ôçxKæÆ¨Xdo±ïÆyþ(±#gþ’æ¾+6™žÿ9О½šúwY2M½`(ôçxK ß_NQìx¹mÐ%ý¶†ãŸor’xRY›eœ&½šúwY2M½`(ôçxK »C’Ú¬z¸›0¤¬eu1¹{ú«ù ¯åù¶ë ct½šúwY2M½`(ôçxK “9v-ó6«=ФcßqZ9ϰô’F\`lk×½‰Œ½šúwY2M½`(ôçxK ¾Êo)ì o3}räˆK ³H˜:* ×?O½šúwY2M½`(ôçxK Éóû™–!HÃʃ62u>Ôü ¹[1æR*Í[ü½šúwY2M½`(ôçxKo¬êÏìýN0;tô€ €˜âЀ+“oŽÇtÎ!ó†hœ½šúwY2M½`(ôçxKN: [CƦ»Ó@O4=Ï9bgΔøµ.#©Ú’ ½šúwY2M½`(ôçxK34)ÿbퟗ>HÜîå-¾.ImTµÏÖÈdÒѽšúwY2M½`(ôçxK+™Ï&B.’þ6_¿Kà 'lžáKzoÿDû/ki™9½šúwY2M½`(ôçxK+¿,§¸ñÙ'îR¶û*]ÐI¸Z+›Rœ]fb°Uø½šúwY2M½`(ôçxK,sÙ3%ºmËå‰Ô¤Æ<[“UYï’ûðPíPÄâRñ}½šúwY2M½`(ôçxK.p‘g†¦÷sQ§«pµWÆ2.©#²¨Ó¹+Q¯}½šúwY2M½`(ôçxK0f(úTw0W(ºJF}çÐ8zTõiÓvŸÎ^uì‰Ò“½šúwY2M½`(ôçxK6íºõ­A¤¡wz¿/¯^g4g^Ù^i5‚ž ªÒ½šúwY2M½`(ôçxK8AÒ!6ƒ×\ æ!`9MlN g`¶ö¹b¼…[½šúwY2M½`(ôçxK?ΛŸß>ðTR°ù^ä·ðmt:syqUŽpjÎ>s½šúwY2M½`(ôçxKC—Úʃžc|µ ’ßC¼-/²¨õŸ&üzKÔÙu’½šúwY2M½`(ôçxKGÌa'⚆à:kï,ÔøÅZmkÛ6!hÃ,ã*Zß½šúwY2M½`(ôçxKQˆ1þs‚µÐ>Æ!"‹Š¶Ty½ ¿£ÅÁÐôœ0a5½šúwY2M½`(ôçxKZéIêˆUë“ä9ÛÆ[Ú.B…,/ßg‰úg6ãÃA+\½šúwY2M½`(ôçxKk€xäAЦë{³^`’ÏGžëŒäÍçÐrÌ´/f½šúwY2M½`(ôçxKlˆTGÕYâ“Q¸&Àl¸¿ï+”­585‡rÑ“ø.ÑʽšúwY2M½`(ôçxKo(ÿqÉÛÕ¯.{¿Ë«d|ÂeÝõ²“Ͷ&õ :x^½šúwY2M½`(ôçxKqòoÒ"I~T£Fb«$—üÈ wõhéãÙ¿Ëýcu½šúwY2M½`(ôçxKrk>¶Tj0óø=›–Îöpé¨ÑpŠqæ-Ä,#Á½šúwY2M½`(ôçxKrà½gÏ]V«Šß;ݼ‚¿2¨ØªŒ^/mò”(ÖØ½šúwY2M½`(ôçxKx'¯™6,úðq}­ä±¿àCŠÑqÁZÝÂH·[øÊ¤K²Å½šúwY2M½`(ôçxK¨¹e»„Ó‡k”)©TÌ•SϪØÈ£;ý3ÿð佚úwY2M½`(ôçxK‚Û;δöCΗÃч͛YAÍ=èXo+ÚV7W_g½šúwY2M½`(ôçxK‰Z—…öÊ~ÔOÁ¡G qóñ"8bÙÿÌ:âß’=¯½šúwY2M½`(ôçxKŠÖHYñ•µõ¯ª” jag¬ÖzˆnF“dr!ÅYE¹½šúwY2M½`(ôçxK‹ô4´žÌ÷¢ÍeËì;= <5¾P_ß{Õcõ!½šúwY2M½`(ôçxKŽ¢‰Ïç «seË(îQíÓ<òPmèˆû­Ö¿€H½šúwY2M½`(ôçxK™˜ÓcÄ‘¾½tº¹M’‘soܦC£fd¼1ZB½šúwY2M½`(ôçxKžJi1ah.Uýèþõ`ëˆìþܯfÀÊ÷²·4½šúwY2M½`(ôçxK¦µ6UÓ¢¯ G'Yykä¤ T•§ØiuLHH…t§½šúwY2M½`(ôçxK§ó/PN°þ­š~ùNѺ ì]æ÷ïoð¦+“¾ß]E½šúwY2M½`(ôçxK­h&á”m&Óêóh\ˆÙ}…Þ;MË=â®Ç`ÑùÂ$Q?¼eYW×5ú)õ@νšúwY2M½`(ôçxKØËë—5õg+6~O–ÍÇIia]JélrMBÎøóú½šúwY2M½`(ôçxKé,"ë;VBÖ\ÂÊòGÒYG8„D•oYâ°Ñú½šúwY2M½`(ôçxKýÝn=)ê„Çt=­JÛǵþÁ³‘ù2@†¬ÇÖÛØ½šúwY2M½`(ôçxKþc¨Ox,ÉÓüòÌùüûÐ7`‡‡XÒb…íf›Ünm½šúwY2M½`(ôçxKþϲ2Ñ.™KmH],qgrŠ¥RY„­\¦u"š6½šúwY2M½`(ôçxKÊaJ~“”ŒÐþUÓ™ùÑ©nE AR'ÂÆ[½šúwY2M½`(ôçxKU¹› å=¼þHZ©Ç7Ï?¶ï=‘úµ™ª|«í§cµº½šúwY2M½`(ôçxKwÝ£ ˆÿ^; æb x  S^ˇæðˆŠ k/½šúwY2M½`(ôçxKÈ<±9"­™õ`tFuÝ7̔ܭZ˦G/î4qÙ9脽šúwY2M½`(ôçxK;‡S> ÃÐì¨#Ëð©AªØryÑÄ™€-Ñæ6¸©½šúwY2M½`(ôçxK“šîôõúQâ3@ÃòäHΈrRjý÷Rçó£ò¼Ÿ`I½šúwY2M½`(ôçxKdW[Ùxš.­Vö4R¯kø ùDxYuéðN-d×E½šúwY2M½`(ôçxKEÇÈ®u Ï»Hü7R}dÝdM®Ø‘<ÍŠ$ÉM…igߎiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€^XÍ3Ëöö9çP‹¿]òÉO -åX§¦ ËÿOŠÕÕ¨Ö䨿¾TF·Dd1‘¨¿T¿¶` 4 ÐA PòÿÿiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€£ÄìÍÝël€¸ÁdtÄQž*p ÜÆ·êò°Æ£|ráÕ ‹]¯V¬™"ò"]÷¡k•–äEFI PART\–õm˜¯2Ï"Ž2Ïi»ôùT»F•-aZ>Üy€€.ä(s*ÁøÒºK É>É;FPµDK¨=Ù&Ô ªÿEFI Systemˆ¡ü;M t?„‘$þ÷=ôD”Iæ‚=Z0NY$Linux RAID¯=ƃ„rGŽy=iØG}äÓUʺï§C®§3L7žkp`$Ž2ÏLinux filesystem€5››Ú¹ò„Ô1-…(š7w´ fÁtö¼Ò,ê:7»GÙf¥AðH‹›é«Ê32:Ã8ÖŽ8aßä‹Ê“Òª à˜+Œ BootOrder€”ˆq·ÃL—i^cQ±¬óŸŽ‚‘ oÿy¢,”e/°üSÃ} ªN¨9ëÙEVk€OŒlObÐaßä‹Ê“Òª à˜+Œ Boot0000tLinux Boot Manager*FPµDK¨=Ù&Ô ªF\EFI\SYSTEMD\SYSTEMD-BOOTX64.EFIÿ€9מTÈÎ Å[Ds=×Ç=!½š Øe¢Ñ=·RšªèQSe EW£?GPä ›QxÒe¿¨aßä‹Ê“Òª à˜+ŒxBoot0003^UEFI OS*FPµDK¨=Ù&Ô ª0\EFI\BOOT\BOOTX64.EFIÿBO€rA‚àÅ@åƒÿN#má6KÒ¯ ¥Blµ_6W3Û­7¾D̨Ïà'& ¸“ØbŒ èaßä‹Ê“Òª à˜+Œ¸Boot0002 ŒLinux Boot Managerçuâ™ u7K¢æÅ8^lËÿ*0G…lÀ¶ÛC¯LA3à)6F\EFI\SYSTEMD\SYSTEMD-BOOTX64.EFIÿ€Ä)å‘ÃÕT-6`7ÕÞá‹Áxå…5 Õ Àá€ØýÞÓçÕà[J¸è{/0æ™V2¡N9“2;°°¶Õy ÐA  ÿÿ*FPµDK¨=Ù&Ô ªF\EFI\SYSTEMD\SYSTEMD-BOOTX64.EFIÿ€ÎÓ{}Õ]n„«)®å\Ò lsV4qÍ‚ê=Ÿ¤fŒØñ ÃSKõ¼^Þ‰9¥”0vµ Œt ÐA  ÿÿ*FPµDK¨=Ù&Ô ª*\vmlinuz-linux-ltsÿ Ó«ì*þŽh‹çœü:VÉ‘Ži 6-V‡”¤B‡ß 23E…PØÝß) –¢–Ò$ò…Æ{î“Ê0‘WðÚ£]Ÿ~A xc ÏÇ€dˆ…_iôYï. 84NÅfÊKÊÖ 2@± ª„ ÓÃ@šµÃH‰”¸1Óå« Ê™®ñ•(‚€ú×NÇ> “´m“NW»ëÚ²Ú¤ “%ˆxž»aê™>Š;“RQ †æƒëXÓEät÷°€WÍMÁ”BGZ¨'CHO;ªˆáB¸ Z¨'ÛÌûDÒ­žÏÚV½êb † ”¾Õ·¢{ºMØ5aßä‹Ê“Òª à˜+Œ SecureBoot€›‡0n»øç•ç¾wV6f»ôQn Þ§¸ µ:=ª¢M\ÄldáúŸýsŸªÛØÀ†|J[H$aßä‹Ê“Òª à˜+ŒPK€šú†ÅA›…pÆ!gË”†Ùü€—X æpá!üëÔs¸¼A»€üšú3O÷›tñ,G¦&aßä‹Ê“Òª à˜+ŒKEK€[øú xÔûÐ3É3˜°) áà ºøš<ÊÎRu _(5"¤—¡­ýP‚*£c¹Ñ$ê|$˲×:=–E£¼ÚÐgeodb€sD$ÉþÇÄ –ô·Lˆs;^ Ÿu¶‚;ÿjñJN 6qœÝT<¼+ñÞŽ~ôÐíùKù&˲×:=–E£¼ÚÐgeodbxiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€”÷<£Y‹[ÿ;)[WˆË¿Í'¡ +7Ü/uâÛ@™àÝTnk»Ѿ_ŒÔIº¯ÈcS½¥ÝTNÐî¾È#. ÐA \ÿÿ€”÷<£Y‹[ÿ;)[WˆË¿Í'¡ +7Ü/uâÛ@™àÝTnk»Ѿ_ŒÔIº¯ÈcS½¥ÝTNÐî¾È#. ÐA \ÿÿ€ê?S +&Z”XÁXXÀàJ¾œ &=™•|{WLc¢e³-§ÿø¸­ƒ(”kûÿe ptÝ‘˜8aßä‹Ê“Òª à˜+Œ BootOrder€*š+ã%»!¦ìÃ2&½¦V) Ó¸ªB$@Ìñíý厊ÐNK—5úÑ}'x?$ì3ÿ&~aßä‹Ê“Òª à˜+ŒNBoot0001UEFI Misc Device ÐA ÿN¬ŸYM…âR,Y²€"¤öîšöÛ 5(Þ¶Ktµ‚ü+ 1—¾0¡` „ä½J¡T¿µFÏ.lö _Œ6*“naßä‹Ê“Òª à˜+Œ>Boot0000 ,UiAppɽ¸|ëø4Oªê>ä¯e¡!ª,FvEƒnжôf#1ÿ€ß]fËCf×E¨FLû&ÁïÜ0\ M8{Ö;/L×ögþ°£‡þG¡ >&¿53ÝÐÆóÞňaßä‹Ê“Òª à˜+ŒXBoot0002,EFI Internal Shellɽ¸|ëø4Oªê>ä¯e¡ƒ¥|>žO­eàRhдÑÿ€ÍÛE1¦ìA¾'Sº&7Öå÷òV =gr´øNÔu•×*,L_ýõ»rÇPâo*®âÆV3º(Calling EFI Application from Boot OptioniÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€Ó\·ÖŽªéañ0w·ºÓ)t +@eмþ½ìŠtL‹‚àt‰àÛÞ'¿#zÊ=âäEFI PART\ز±]ÿ_f"Þ_f¢É|cFŽÏF’Ì·ã쀀Or¯=ƃ„rGŽy=iØG}äp©xFw–C‚¸ÿǺ؉xÞ_fHah!IdontNeedEFIÚùÑ û¬BŸ9ûºF$ ½ÿ'(s*ÁøÒºK É>É;˜çYÃjY¶B¶öì¢B™(ÿw€Ðæù9ñ0Jƒ—_4ÿg¥s®+>å L•W± >!f>-#ãÁ®œäµÞ X¢—3#6¢Ø°Â¾ ^p ÐA *(P˜çYÃjY¶B¶öì¢B™0\EFI\BOOT\BOOTX64.EFIÿ€& ¢4?¸Ÿ/‚Y–uGO -Pm pýxÎmèÐÌ}\§N.ià<¹'bØ¡c¦P AY?) ¯ [³ç¹¸Cú;ñz…‡| P1ö$/ ²oûñ©»8 ¥¡Ü´KµóÞkDÂÂB ¨?’ÐÀjEgrub_cmd: [ -z (hd0,gpt15)/boot/grub -o ! -e (hd0,gpt15)/boot/grub ] t¾½Yáà>3Ʋ‚ð,•¦9š N–x…í >¾ø“áÆNJ=™$Ûl*²G£mªÞöJ;grub_cmd: [ -e (hd0,gpt15)/boot/grub/x86_64-efi/grub.cfg ] Ò5†¶áF8Áw~È7`@t + z…¥õ„¹œàjèý—îÂß”±È­0\ñDÙ¿÷—¼Ï0grub_cmd: [ -e (hd0,gpt15)/boot/grub/grub.cfg ] ‰9 Ô§¤ÛDÚ(à²XPçJáµ¢ Òмÿ4qí…Ç5êérá‹diy€O64ºqÌÓ÷;"0grub_cmd: source (hd0,gpt15)/boot/grub/grub.cfg çßåÌf¨gIÂ^Ž]ç {× 1“u‹õu.î§›z{ï`w.ÿË~œ¨µýBã<ž‰S¿(hd0,gpt15)/boot/grub/grub.cfg Üg¼É«ÂAù*kah= ¸ˆ«›l J0ðDü.:Ù3 \õó—"(Øþ-Ñд* {TLgrub_cmd: search.fs_uuid d64f335d-4d71-46c8-9379-3375973830f3 root hd0,gpt1 ÉÛØ¼9(ù=AïAv£A]òÕ„ë g˜E·˜`Ü~‡ |{}Ô+SIåF2»ú‚§@T*grub_cmd: set prefix=(hd0,gpt1)/boot/grub ~…Ÿ³}W‚, Ó¶6ç…:ÿ Q7%|Üì Î~ ƒÁ ó÷ìñáÞF¸Ó/Iºew‘,(hd0,gpt1)/boot/grub/x86_64-efi/command.lst ð‘e\zÇ1N°ß!“ÞGbb 2ü]èÀ¥Ü ~¶ Ê1§~³GU9áÙzECÜ¡¹²lW'(hd0,gpt1)/boot/grub/x86_64-efi/fs.lst ÿÒ9Œñ R2””Ö:Îëòš vo8©I'þ›{Áè ð6>wŽÆèúê'.uÓüC+(hd0,gpt1)/boot/grub/x86_64-efi/crypto.lst f·&ÆÖKÁ ӔЕ(õꔓŽô FøˆÅ/6ºù¶-`¼Bj1J­ZøjCb©%¡ßœ-(hd0,gpt1)/boot/grub/x86_64-efi/terminal.lst „¾åh¯.2jÜãD+çÕ ‡M>æÕwm„tüºívÍÔO2W-„T3ïq84~†m}3grub_cmd: configfile (hd0,gpt1)/boot/grub/grub.cfg f)µ BQ¥ÚÕ›æšú;œ×sqõ Ep@ìû.ü°b´¸3íEØùÅw? i~·}dpVwýÜ®(hd0,gpt1)/boot/grub/grub.cfg >\×êÜ.+/•mAù ãs/¸3 ~+4“º£ù䯍6(-fµ…V’îDÔoâ ÛÁs.grub_cmd: [ -s (hd0,gpt1)/boot/grub/grubenv ] Ø$ƒx˜W\¢ü®2þÖCà „Ö& BCŸÚQCDœf„0pmâpÇd‘+va€å”¼×]–¤l(hd0,gpt1)/boot/grub/grubenv ¤›©I@grub_cmd: [ 1 = 2 ] ª AÐeRÞ¢¤{ŽY'J Y5qkõqki1óøä b`hPÏÄ=%ÿ,¤uMÌÜëgrub_cmd: [ 1 = 1 ] Øó`p…°çÐŒ+Y%rÙ·™Ñ kYÿ‡bZ 'fÍ]arð Ö3x‚;ô¥Q¦(øt»¶BÏgrub_cmd: set next_entry= ªx¶>—] îJ÷ä¿ È1L¢ç(b JnXvòبgñ ž61­”£t„æ‚y žH¹*«îgrub_cmd: set prev_entry= icD0üÕ‡ÈwGsÍ>¬ü/'Ì ý̤Ž,š«l¾C[\Ú›9]gªU¶.~\㥠À9¬2grub_cmd: save_env prev_entry q ¿#|š½©A2H¾Ç°û Î$¼¼ µÍG3Œ ÇÕõDmy“nD: –±’§½egrub_cmd: [ ] q ¿#|š½©A2H¾Ç°û Î$¼¼ µÍG3Œ ÇÕõDmy“nD: –±’§½egrub_cmd: [ ] u@‘ E+»î0«â‰¯—>Í×àïk :‰@¿&u}ó6Œ¶Ô\òuo2>uÚöš—ÒѼXgrub_cmd: set default=0 õ°gåœ?g±›ƒo¾é複¡œÝ Eh6·X1¤-dZµ40/¹÷B­ª7·ýáR!]iâYûgrub_cmd: [ xy = xy ] ½R å eüõÂÑ*‹è'~C€# ñ}MûK—ñbFc,!±¬!%É\ˆ™î埻46U#grub_cmd: menuentry_id_option=--id bHY›® x̽¡…í/΂íAâ— Jð»7 ž;y‚}àL“^2Õ+R€GküPÓm†^%grub_cmd: export menuentry_id_option q ¿#|š½©A2H¾Ç°û Î$¼¼ µÍG3Œ ÇÕõDmy“nD: –±’§½egrub_cmd: [ ] }ÂrÚ°╉a»™¢ãnÂJ ß$ñÊæ´(ýЛÁKß%_“ð]VÃw$…–÷=_!grub_cmd: terminal_input console ^ Gõ4± ÖŠRU@æ þ×É0“J#'Ÿ¡w£˜‘ͯlÍ"¼ÌéjÍÑ"grub_cmd: terminal_output console ª AÐeRÞ¢¤{ŽY'J Y5qkõqki1óøä b`hPÏÄ=%ÿ,¤uMÌÜëgrub_cmd: [ 1 = 1 ] OD¤§§R>cwê–Ó‹6»l"Ø Ó§“ôq¶¿è׃õæ)1L­GcÔ‰†¨ÍMòTu3K@ô›grub_cmd: set timeout=0  WT‰ZZœâ]ÆÂP&'Œ-cg |Ú•ý…‘‰ÐÇÂ̹ÀVr˜E‰ä€žÎæeÖ)Ï},grub_cmd: set menu_color_normal=white/black Ô¥®Á¼ÊþÆT ÙË$:¤eØ7 oyŸàìµÄ»L•£ MÉ„” ;F>Â^DBF4Š*4grub_cmd: set menu_color_highlight=black/light-gray ìÜ­tZÐ,„@ò{N‰×gtç lôŠL&ú¤È®G³}R°ÿ0•Â<5£»ˆr¸|ˆ>¾<grub_cmd: set partuuid=78a91070-7746-4396-82b8-ffc7ba90d889 ÿÅÿi“=Ù¡¦†8Î6Xï "iÊ ”y e0`¥VJ¾þ—ÒÃÑ<6ïû$ŸWÑå>Ûµgrub_cmd: [ 1 != 1 ] ²/]µySüé_†#«GH;qÜ V®VGT5žÏeJ:¸~Øz#Ç€×ðöwÝ{]"grub_cmd: set linux_gfx_mode=text îðúDNY× Ža_%bˆ&çþÝù "àA%µNë2p$WYª>‹Ó·zd}¹ˆ¶±êüi`ªE grub_cmd: export linux_gfx_mode ÊJwl‚€5mm ˆÚ§úd· F¸6Ÿ:=‹ÉrJ?N$.ÉUeºa¢) 2„ÿgrub_cmd: menuentry Ubuntu --class ubuntu --class gnu-linux --class gnu --class os --id gnulinux-simple-d64f335d-4d71-46c8-9379-3375973830f3 { recordfail load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 d64f335d-4d71-46c8-9379-3375973830f3 else search --no-floppy --fs-uuid --set=root d64f335d-4d71-46c8-9379-3375973830f3 fi if [ "${initrdfail}" = 1 ]; then linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 initrd /boot/initrd.img-5.4.0-45-generic else linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 panic=-1 fi initrdfail } शí]wìdBõþBH᯻õXö $ôwVk…2Ç{ô^àFRE91³å×¾´ grub_cmd: submenu Advanced options for Ubuntu --id gnulinux-advanced-d64f335d-4d71-46c8-9379-3375973830f3 { menuentry 'Ubuntu, with Linux 5.4.0-45-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-45-generic-advanced-d64f335d-4d71-46c8-9379-3375973830f3' { recordfail load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 d64f335d-4d71-46c8-9379-3375973830f3 else search --no-floppy --fs-uuid --set=root d64f335d-4d71-46c8-9379-3375973830f3 fi echo 'Loading Linux 5.4.0-45-generic ...' if [ "${initrdfail}" = 1 ]; then linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.4.0-45-generic else linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 panic=-1 fi initrdfail } menuentry 'Ubuntu, with Linux 5.4.0-45-generic (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.4.0-45-generic-recovery-d64f335d-4d71-46c8-9379-3375973830f3' { recordfail load_video insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 d64f335d-4d71-46c8-9379-3375973830f3 else search --no-floppy --fs-uuid --set=root d64f335d-4d71-46c8-9379-3375973830f3 fi echo 'Loading Linux 5.4.0-45-generic ...' if [ "${initrdfail}" = 1 ]; then linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro recovery nomodeset dis_ucode_ldr biosdevname=0 net.ifnames=0 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.4.0-45-generic else linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro recovery nomodeset dis_ucode_ldr biosdevname=0 net.ifnames=0 panic=-1 fi initrdfail } } '?\€Á.“\7ÂÏãáa¼B׎ £t0• ƒp!ëÌùŒŒ1å“ãfB”6á55„Çìr1grub_cmd: [ -f (hd0,gpt1)/boot/grub/custom.cfg ] £2móBW^Qù¡ÈÕÑzïòÐ ÕGWX1¿oósƒ°·Žy #r£¦zÐÑÊ5ÛLgrub_cmd: [ -z (hd0,gpt1)/boot/grub -a -f (hd0,gpt1)/boot/grub/custom.cfg ] ÇjeëÚj£Ú«¼ÖH;ð ô ¿]¤fÀ÷x™ ÜÈú,Eaº’‘-_¼JÁãûgrub_cmd: setparams Ubuntu ˜ÐføÿÐFºË8±Œ¾é­§) ¥~~(nüNê‰e@ñ:8Ì’ä'{í‚ ígL”¿.­grub_cmd: recordfail ºÁp…þõ6b¥ ï¿6hDÀtÿ d½¨ö[…׆‚H¢’ÄIf È÷PuÁ ‡®Y¤Û@ágrub_cmd: set recordfail=1 UÏÖF>ó4«¶´€€³>Àc©ÀQë ϤgoþuGçzf 3µ›>í4Ù³£Ò`‘«Ygrub_cmd: [ -n true ] Ó_kqmx5²a‰D»_eâ… Nz"ùk®F}ðòiuà¿vÖ¹)“0eºæ¨\e0ä`¿grub_cmd: [ -z ] ’^æ›|ŠÄ“|¾GÕÈSQØi´è× Î,Âwº;Ç[f!cëãp4MK®×_µ½@¶ºßgrub_cmd: save_env recordfail åžfÖì„ G$÷‘é)ñSáD v&«Ø¾tBÂåu6J>•Ë:;Sû lFtÔÆRîg¹Šb×TËòÕÜ ÚãÖn‚ǔė„grub_cmd: insmod gzio -èEÜè¥ݺ F†v“2[ui †Thò佟 ÄÿÝ¡3_@]ßoñƒ³sõè’Mgrub_cmd: [ xefi = xxen ] ¤áÆõy´|–AÑê!pæù#ÉA bÍv t.FÆÿFÎÝóa¨'þÆWYÂG”grub_cmd: insmod part_gpt ¯?«¬ž\V¸/ «˜2‰ª»öï ¸8¤Ò† û±z·ö eY ›; ›1ØÒû grub_cmd: insmod ext2 Ëñ¼³÷, M°Ò~énʪš0Êgrub_cmd: set root=hd0,gpt1 õ°gåœ?g±›ƒo¾é複¡œÝ Eh6·X1¤-dZµ40/¹÷B­ª7·ýáR!]iâYûgrub_cmd: [ xy = xy ] ›ê¢ ~D“¤»1ñ?m•‹4)² ÿ<‚eGP6zOÁuÇ~—LSQtpݰ*ú#¤ôœgrub_cmd: search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 d64f335d-4d71-46c8-9379-3375973830f3 ª AÐeRÞ¢¤{ŽY'J Y5qkõqki1óøä b`hPÏÄ=%ÿ,¤uMÌÜëgrub_cmd: [ 1 = 1 ] ¶øþÂj~¶_9'ªC¯nŽÁ„næˆ ×£ÝvòßW<ÿŒOÖP‘ízÓ¦C}¸°Û3%ưíœgrub_cmd: linux /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 Š {‚&­Yµ¬CÊJý8p„Hë odaTléûî 3Ü­uöõSNÏz9)µÈÀÙ0“¶äâ/boot/vmlinuz-5.4.0-45-generic 10ýÚ#G´EÙ ºÊ%œè _“8”ë¶š‚ 0wÓú¶ûØ&jaäÿwÑTïœkernel_cmdline: /boot/vmlinuz-5.4.0-45-generic root=PARTUUID=78a91070-7746-4396-82b8-ffc7ba90d889 ro biosdevname=0 net.ifnames=0 console=tty1 console=ttyS0 É,µ•ïB–ͺµðÁ^O»; KßʆYŠ.Ê™Ú ]~´7¤¹)ao$:A“lD`ÔF3grub_cmd: initrd /boot/initrd.img-5.4.0-45-generic dsó‘”e'ôž_8··ÊçQ Fœ@ÐiF™¨ïÆl“þˆ-ð,è÷®FWnªEuR"/boot/initrd.img-5.4.0-45-generic ŒiDÅퟄ?Õõ¼2”çÛ v¼lmpÎ4¢KÚ&5„íÐý]”ù ¢Ý^P é‹=ògrub_cmd: initrdfail UÏÖF>ó4«¶´€€³>Àc©ÀQë ϤgoþuGçzf 3µ›>í4Ù³£Ò`‘«Ygrub_cmd: [ -n true ] †6^¼Þ‘¨‹ÑÉ{HdçŽfÙ~z 6 Îx3% 5?Ž={yñïÊ»%¬vWdö¤@>ìIt6grub_cmd: [ -n 78a91070-7746-4396-82b8-ffc7ba90d889 ] £¥V:ÊÍ:5Eó‹þÄ2‹áÛm P¾r>'!Ž-²9(²"D„Å“—Ž s¸ôUë ªH`grub_cmd: [ -z 1 ] ŸP–{Àf‚iDj©/+ˆb  X9ý›þ¾;Þw9ßjƒ 7âZGÿ¦¡d´¢ PÈgrub_cmd: save_env initrdfail€D:k{‚·¯VO.9<ÙÕ£ˆ·úJ˜ Ø=k{…­5޳¶®j‡:·ï#¢cRÅÜOªZîÚÏ^´Exit Boot Services Invocation€GUEÝÉx׿Ð6úÌ~.˜HŸ µOuBËØr¨ꃛ+t|~½^¦a\@ô/D¦Ûë (Exit Boot Services Returned with Successtpm2-tools-5.2/test/integration/fixtures/event-gce-ubuntu-2104-log.bin000066400000000000000000001020401412464516500256120ustar00rootroot00000000000000)Spec ID Event03 0?p‹Û¯òfUµ@6GL  Ðüñ2¨ûõ¤á¥Œ×MÒ5}çP;[jýZy‰©Ž¾ m±‚.BÏ’4ö§ŠÅËIô›ÁÄ9?71a!‹¶ߊ÷¦ŒΦ‚ae‰¿ c0GCE Virtual Firmware v1žŠ÷Bqð@’U'Ár7i¬þ~ {tÞ£Lé´—U««èºÉ­R=ZÝìN/¢˜ã®hý'o §Mæ'¤­+{FñÔ (ë?^àU«Éˆ?,§Ù¾ßŽÈÈHüåª Ò/PÎxõ»ñ^ GCE NonHostInfo€WÍMÁ”BGZ¨'CHO;ªˆáB¸ Z¨'ÛÌûDÒ­žÏÚV½êb † ”¾Õ·¢{ºMØ Ï¤âÆõrb{ðmViÌ*±ƒXÒ{E¼cnÁ ϯ·@øG¦§K^®Ö·32ì5aßä‹Ê“Òª à˜+Œ SecureBoot€Z½”«ó>4§›=“ÓPçBØìØ Û»ã—fX…eÅ̘¢®¶äJ‘xÉñ“[ÒAóƒrD„» §cU<–w Ó¥æøàÁïÍòUZ÷Sú:jþCë{* ô¦øØäÝE–hó°àJaßä‹Ê“Òª à˜+Œ&PK¡YÀ¥ä”§J‡µ«\+ðr& ÒúÒˆ¤G—’[ªG»‰0‚ö0‚Þ  ÕJègƒ]ê0  *†H†÷  010 U newpk0 180821215115Z 180920215115Z010 U newpk0‚"0  *†H†÷ ‚0‚ ‚̹Õ|ømkcêÉbô “Éþã|,EÎ…RRH|ûC&¿ ¥‰°òÝÇ6èi•ªŒoТ#o4ÂO±žkÆú¸”ÁœŽp‡‘BÎi!“}ÚuŸ¿1 PÁï€#û¾;Vã ×Gê0¯Ô]©c‰¢ü9á–¡‡Ã=&²Ó¢lìÈ—×ÎÚ겕<³ÎŠÏÚ:Qˆ?%°K>ÌÝùÚÛQÕ‘š¡½ˆâñ´ñ³’·ãgæ­ŒjÜ'?ÜÔNlÁ½ïÞV*ÚY` yÓ©|WýQa7}ä·n•ðR›CžÜH<ͼ9Ÿ£èG F¸6Ü’³•¨ÎJãF#XK£S0Q0U˜P„Bó/Û—‚'(—t1F^`ËÅ0U#0€˜P„Bó/Û—‚'(—t1F^`ËÅ0Uÿ0ÿ0  *†H†÷  ‚Š¡R?ªç½°$«‹­2°Iý{4Ë;€v`=ŽÜÊkiÂ[”踜Œ,×¼¬}‚YõÄ.¢l¥ì˜ð1#6øË0ƒg::+b!`,ºõ.ù(nÊfpX(†gi„l'X%œPép¸`nT…J¯mE¦[4ü&M<á»$.yàÑȬ|Ù8GCk3PWãsž¦‡ÝÃâJüs{K ‡Çƒ 6Zêi‡@„ ,”€/=®=ËpÄ5¹>q²£Æ­Ø$?}`«o îzšÏuŸèL«ÍQ‡hX3²Ù¼8%*˜KEûg3›%œ?¬¤CDÌÍÓÈ ná€ðPy¶ÌBé.èZtÙÂviÀâ b&GØ[Šd}-.f‚Áb {l¦·"ZfWÂVµ‚ À§¦@“íy΋V—=ÞöÚ‘¿ ëW’³ÈBB7Bµ)C¥‹ß#(¤4“~2xˆ>aßä‹Ê“Òª à˜+ŒKEK¡YÀ¥ä”§J‡µ«\+ðrüÒúÒˆ¤G—’[ªG»‰0‚è0‚Р a ш0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110624204129Z 260624205129Z0€1 0 UUS10U Washington10URedmond10U Microsoft Corporation1*0(U!Microsoft Corporation KEK CA 20110‚"0  *†H†÷ ‚0‚ ‚Ä赊¿­W&°&ÃêçûWzD] ÚJåt*æ°ìmëì¹ãZc2|Oã §8“ŽÆõà„±š›,çõ·‘Ö áâÀ¨¬0ßHóPšd§QÈ…O †Îþ/áŸÿ‚ÀíéÍÎôSjb: C¹â%ýþùÔÄ«â#‰p·¤Mì®åœúÂ×ÁËÔèÄ/å™î$‹ìò‹êÃJûC ~µG’lÜæ‰ëõ3ë*qåùƒ<ÿ% /hvFÿºO¾Ü­q*XªûÒy=ä›e;Ì)*ŸürY¢ë®’ïö5€Æìä_ÌvÍïc’Á¯y@„y‡ãR¨è{i£‚O0‚K0 +‚70UbüCÍ >¤ËgÒ[ÙU¬{̶Š_0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚Ô„ˆõ”Ê*<û*’ × ÑñèRf¨î¢µuzª-¤vZêy·¹7jQ{döádòg¾÷¨x½ºÎˆXd ÖWÈ£_ÖÛÆÐiÎHK2·ë]Ò0õÀõ¸ºx£+þ›Û4V„ì‚Ê®A%pœkéþ×–å甲* Kÿ(){÷×|¥Ñv¹Èyí’œÂþßo~l{ÔÁEÝ4Q–9å^VØ–ô¦B³ wýòqVÌŸ†#¤‡Ë¦ýX~Ôig‘~òå ‹Š<‡„ëãνCå­-„“Žj+Z|DúRªÈ-»àRßøš=Á`°á3µ£ˆÑe ç¬|¤Á‚‡N8±/ Ňoý.¼9¶çæÃàäÍ'„ï”Bï)‹FA;gØùCYeË ¼ý’Oôu;§©$üPA@yà-O j'vnRí–i{¯÷‡ÐE­Sû0ª76aÚJi4ØhíÖÏl” ÓÏl"y­±ð¼¢F`©ÄÂ!‚ñýòèy2`¿Ø¬¥"KÊÁØKë}?W5²æOu´°`"S®‘yÖ›A†Tp²Þ 5|°4rº—`;ðy뢲]¢¸‡Åéöµ—%o8Ÿã‘úŠy˜Ãi·£ —øÊ®×ÄóÀuk4 µ™`ó\°ÅWN6Ò2„¿ž€ ¢œ'û¢a€`³"ÇÉr bº8Ã„Š”bù‡tņéÙTç)!³¥%A$¶62̯Z 5 Íbº¾öúà[î|<å(ó(yÓwŒ6ù»ñêóbB:؛Ȧ’ƒ­(!Åü7k ˲×:=–E£¼ÚÐgeoG db¡YÀ¥ä”§J‡µ«\+ðr@$ÒúÒˆ¤G—’[ªG»‰0‚0‚ø  aÓÄ0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110627212245Z 260627213245Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U"Microsoft Corporation UEFI CA 20110‚"0  *†H†÷ ‚0‚ ‚¥lLÇE jK ¤À‡u CTdàí’} ²s¿ ÆJEa Å-–Óõ+ ûMI›A€<¹Týæ¼ÑĤŠAŠ\Yƒh2»ŒGÉîq¼!OšŠ|ÿD?2²&H®uµîÉLJ~䂚xwM °½öÓÓ¼ú+¥Q8]õûºÛxÛÿì –Õƒ¸é¶À{@{á('ÉúïV^æ~”~ÀðD²y9åÚ²b‹M¿8pâh$É3¤7ÕXi^Ó|íÁSçN°*‡caocYê²+y× agŠ[ý^­‡º†gOqX"""΋ïTqÎP5Xv•îj±¢Õ£‚v0‚r0 +‚70# +‚7øÁk·wSJó%7N¡&{ p€0U­¿C ½‚pœŒÕO1nÕ"˜ŠÔ0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚5Bÿ0ÌÎ÷v ­hX5)F2v'|ïA'BJªm8HYUóéX4¦ ‚ª]­‚Ú€ƒA´ò¹ó]ñPù³U„B( ½²®QÅÀ¬—•!Ûüwž•s‘ˆÊ½½R¹P ßWž aí åm%Ù@@ÈΣJÂM¯šT½Ç¼¹+=I+2üj!iO›È~B4ü6‹ @À³š%u'ÍÉ£ö]Ñç6Tz¹PµÓÑ¿»tßÜ€Õíô/k/ÞfŒ°#åÇ„ØíêÁ3‚­VK-ñh•ÍÏðrð®»Ý†…˜,!L3+ðJðh‡µ’U2u¡j‚j<£%¤í­×®ËØ@Y „Ñ•Lb‘"tŒ=GD¦ä°›45±ú¶S¨,ì¤qȸºèDfäGTŽV³Ÿ˜²†Ðh>#µ/^P…Æ‚_A¡ô. à™Òluä¶iµ!†úÑöâMÑÚ­,wS%27ÇlRr•†°ñ5ajõ²;PV¦2-þ¢‰ùB†'U¡‚ÊZ›ø0˜T¦G–%/È&äA”\?å–ã…[<>?»GrUâ%"±Ù{ç*£÷Fà Ö‰ã5'bq¦ïÐ'  Y7`ø8”¸àxpøºL†‡”öà®Eîe¶£~iu’›õ¦¼YƒX¡YÀ¥ä”§J‡µ«\+ðrëÒúÒˆ¤G—’[ªG»‰0‚×0‚¿  avV0  *†H†÷  0ˆ1 0 UUS10U Washington10URedmond10U Microsoft Corporation1200U)Microsoft Root Certificate Authority 20100 111019184142Z 261019185142Z0„1 0 UUS10U Washington10URedmond10U Microsoft Corporation1.0,U%Microsoft Windows Production PCA 20110‚"0  *†H†÷ ‚0‚ ‚Ý »¢ä. ãçÅ÷–i¼!½i33ï­ËT€îƒ»Å „Ù÷Ò‹ó8°«¤­-|byÿãJ?5 pãÄçkàœÀ6uéŠ1ÝpåÜ7µtF–([‡`#,¿ÜG¥g÷Q'žrë¦É¹;S5|åÓì'¹‡þ¹É# o¨F‘Án–http://www.microsoft.com/pki/certs/MicRooCerAut_2010-06-23.crt0  *†H†÷  ‚ü|qQ¥yÂn²ï9>¼«\`ìß¨Ó éôö–…¶QˆfG¢°=*hw»‘Lb{¶ÁǺz‡4Kbz™éÊüÎJ7É-¤W|þ=ܸZúÖij…:ê³Ùnäi!7ÞÑöugÓ“W^)9Èî-áÍäEs[ÐÒÎz«‚FXÐ^³g¯l5ò¼å?$â5¢ uöV™Ôx,ÑëЈªñߺ~,c·›#!ÄùxlâX6+‘̤Ùò-ºù”@íEñΊ\k>«Óp* jà_GÑÕc 2ò¯×6*pZåBYqKWº~ƒð!<ôÁŹ“ˆE“†é± ™¾˜ËÅ•¤]bÖ c ½uw}=óE¹Ÿ—ŸËW€o3©Ïw¤bY~€sD$ÉþÇÄ –ô·Lˆs;^ Ÿu¶‚;ÿjñJN 6qœÝT<¼+ñÞŽ~ôÐíùKù ÌnðÆê™ª#ø¢€B>”­Ùm ëQ€POÀ÷¤ ³aÓ›Ö©^Áh †íj°ù‚&˲×:=–E£¼ÚÐgeodbxiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ð€¶ ëïp®$Ùþ‘=ÐÆÒ´àØ ÀI AP“Ç á«¡õO‡®wG"1Ëôí@¦„vÔŠFQUã ¬uŠôlž¨øc%CÄD0mÐlÊžüŽÏ9l0•ô{¦“¼ðaèuŸÁ9‰:aßä‹Ê“Òª à˜+Œ BootOrder€ÝèxÍ®C×ZG™šèrº‘\ê‰ ´¯¡O¦ÝR¡Õ(g½ÒN½}œŒù¯ƒÁ4•;- SÞuÒ¦# 7 ÷ÝÛŒ ´Á8Ã¥>ªT|Þd<Ú $äDÇN-bæÀa1ÂîU¦aßä‹Ê“Òª à˜+ŒvBoot0003bubuntu*(P@÷¦nï%iBƒo!ëò4\EFI\ubuntu\shimx64.efiÿ€"¤öîšöÛ 5(Þ¶Ktµ‚ü+ 1—¾0¡` „ä½J¡T¿µFÏ.lö _Œ6*“ #­ Rañ/4 ½ŽFv bÖ´Õv¤ñþ¡ÆKÆV±Òެ÷zæégÅÒ©‹út˜naßä‹Ê“Òª à˜+Œ>Boot0000 ,UiAppɽ¸|ëø4Oªê>ä¯e¡!ª,FvEƒnжôf#1ÿ€íÛèÄA+ù˜‡™Ô{ãÚ7ô ¨°ex,ÿ¾ÿÝhŒõE |–0«fe×*©%|òÛ6 œ o o½6Y?WÀ–:Ø9…qM–t–NDrG([Æ C(nàm¥ «ˆõ»/Kžœaßä‹Ê“Òª à˜+ŒlBoot0001UEFI Google PersistentDisk  ÐA ÿN¬ŸYM…âR,Y²€1—‰À=^—§t®Êì’ôŸ ¡:‰‹ƒf4¦,açÎÔêZï½®ZšÚ9¬¯„—¬º €¡Þ|Óׇdz,xEÊx´}Ùö£3Q®'àcsD[góÙDó¬]¦4KËøiƒaßä‹Ê“Òª à˜+ŒSBoot0002!VirtScsi(0,3,0) DiskVirtScsi(0,3,0) Diskÿ€ÍÛE1¦ìA¾'Sº&7Öå÷òV =gr´øNÔu•×*,L_ýõ»rÇPâo*®âÆV3º w Ú²1+NW¨M†Z!å²îgz!*Ú ˜˜€xÓ×@ö4kþ º©8Ê Cšq(Calling EFI Application from Boot OptioniÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ðiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸ 9CA·,Ò'ÅÆ°~ø ߨa6Ä)+ŽWes­~Ù®AŸX´¹qÉïü`á­Ÿ‰ð€PîÏÎÂPȱÓV©!~ ל*n -i¤­¿_XÉWý¶®Ü†êzPÉ;@÷¦nï%iBƒo!ëò(ÿw€’æì“` žÇò:ßN¥U;N#d Ùœ“ü°BÛå'»Þ7uüðÝ[ ˆ¡•ÔLÅu6öõ! Øœ‘h±V%\miVÑY4"¼PDm)Áªª†ÿð¦3ó$¬Á.TtyÎP§Zœ@Þ½À’| ÐA *(P@÷¦nï%iBƒo!ëò4\EFI\ubuntu\shimx64.efiÿ h¼ì`åÃòûÝš©ª‘Ú’ü‰?) /k VGd̦t^Í—‰Žtí8‘ÇÆ<æñ}È&J 3Wêe_ ŒªÂeÏÕè |Ç%O£ñåê4Z‡<÷aG*/#ñR—õ\þ$MokList â„¿YM¬Þ5€÷±r=¼Û_5÷ öE< Ñ{Q6¬íŒa,èìmŒï§ü÷Ìèæ™ß óÌu¥$¿·êr¥×Á9·Z>¨|rJ+T¯ù*œGÿȯÂê“Ò8Myƒ% (hd0,gpt15)/EFI/ubuntu/grub.cfg N+RKšð hò$÷\5pï`>j !2á㸗kd`/3Âgëé%×Ò¬Ç%–µE ¤ ì|;J®( ‡ ô¹pµ!ã5W²ÍiµæilæK%†’Ó0ÆþÀ‚˜«f­³Ó†bHCgrub_cmd: search.fs_uuid c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a root ÉÛØ¼9(ù=AïAv£A]òÕ„ë g˜E·˜`Ü~‡ |{}Ô+SIåF2»ú‚§@T Ç)# =ذƒS—Æ9v<“þ–ÔãyÙ€ÐCÇø«£Èö ­ }›*ŒëÙv&8!e*grub_cmd: set prefix=(hd0,gpt1)/boot/grub ~…Ÿ³}W‚, Ó¶6ç…:ÿ Q7%|Üì Î~ ƒÁ ó÷ìñáÞF¸Ó/Iºew‘ ±ñ1¹nÅ`[åË:YwGõà3*t@ŒeËkeNò¨É úk‡U¼üZ‚,(hd0,gpt1)/boot/grub/x86_64-efi/command.lst ð‘e\zÇ1N°ß!“ÞGbb 2ü]èÀ¥Ü ~¶ Ê1§~³GU9áÙzECÜ¡¹²lW sá|>£mêWow(c “tiTò¾‘CëKvpas×Ù¦Œ2çÉt°ÿ\í‰`9'(hd0,gpt1)/boot/grub/x86_64-efi/fs.lst ÿÒ9Œñ R2””Ö:Îëòš vo8©I'þ›{Áè ð6>wŽÆèúê'.uÓüC ÇÐåAe°Òj`Ö;‘Ntw‚]^͇„ 6CLkÙVrTA¸*f¶X6½8úÔ+(hd0,gpt1)/boot/grub/x86_64-efi/crypto.lst f·&ÆÖKÁ ӔЕ(õꔓŽô FøˆÅ/6ºù¶-`¼Bj1J­ZøjCb©%¡ßœ €$ýMñêýkº6Å–Ã:ûµ'ãkXÁŸ­ÎÔ{È®’øžóÊï#F³½T\ýØÞ-(hd0,gpt1)/boot/grub/x86_64-efi/terminal.lst „¾åh¯.2jÜãD+çÕ ‡M>æÕwm„tüºívÍÔO2W-„T3ïq84~†m} «ŒS¬ÌGÿïUĶr[KÚÇëcäí~ÂÕePë —JåFµß¶±¹ÆVŸG7­š×»3grub_cmd: configfile (hd0,gpt1)/boot/grub/grub.cfg 5¦ël}ú¹Ñ5ùi’nQV `±yi (JVý#Äê†Ç… KèÎ>-¤’ ¶S Û³vI‰{o}4R§NkƒÓÀYH„”Ÿá¼Ó蹞%ÅÍ£¥Ói Ù¡(hd0,gpt1)/boot/grub/grub.cfg >\×êÜ.+/•mAù ãs/¸3 ~+4“º£ù䯍6(-fµ…V’îDÔoâ ÛÁs V»Í†G¦å¿çÈqo6Îÿô¬¡´ÃïJÙôzlîh»ƒätf0¾×ÐSá*©u.grub_cmd: [ -s (hd0,gpt1)/boot/grub/grubenv ] ÏòÈ•”C ˆ˜‡þ!*Cݽ«]2Fgrub_cmd: [ = 2 ] ºE+ð ˆ(³]é‰À…8 ‚¤¡NC¤÷a®c(] ðZñ9ò`úå{, szó8+ ®aÄ[<%Èœê?}ÞädŽw`†÷Ö/´¹ÁÕaH¡¾¿Þj9SDV{SŒmðmžgrub_cmd: [ = 1 ] q ¿#|š½©A2H¾Ç°û Î$¼¼ µÍG3Œ ÇÕõDmy“nD: –±’§½e ".%på/r»™óï—ËuÔÞ:TUƒêMfV€g?t»'ÐÊ\³µŠ%ìxÎHQgrub_cmd: [ ] u@‘ E+»î0«â‰¯—>Í×àïk :‰@¿&u}ó6Œ¶Ô\òuo2>uÚöš—ÒѼX kö$/ްÊrÆã¥ÔƦ.XXDdèF–Íg0nòÛŒö%•-_ÙªÞý9G—@grub_cmd: set default=0 õ°gåœ?g±›ƒo¾é複¡œÝ Eh6·X1¤-dZµ40/¹÷B­ª7·ýáR!]iâYû ±øÐ6®ý2ÎwêBn{=®ãxÝy®Ú–;,S‰‡‡–,éêåWÌéJgrub_cmd: [ xy = xy ] ½R å eüõÂÑ*‹è'~C€# ñ}MûK—ñbFc,!±¬!%É\ˆ™î埻46U †a•?QŒ‰Œ¹@|ƒ¦Tý¯˜Ò]™ËÃÑRUµ2ºÐD÷¦;)aîÑ龬f#grub_cmd: menuentry_id_option=--id bHY›® x̽¡…í/΂íAâ— Jð»7 ž;y‚}àL“^2Õ+R€GküPÓm†^ •-Î9©âƒî{=ï¶dü”*•˜½‹m ©„;(xnÇÂk¯¢Œ <ûˆÛ·µh%grub_cmd: export menuentry_id_option q ¿#|š½©A2H¾Ç°û Î$¼¼ µÍG3Œ ÇÕõDmy“nD: –±’§½e ".%på/r»™óï—ËuÔÞ:TUƒêMfV€g?t»'ÐÊ\³µŠ%ìxÎHQgrub_cmd: [ ] }ÂrÚ°╉a»™¢ãnÂJ ß$ñÊæ´(ýЛÁKß%_“ð]VÃw$…–÷=_ \ÓLîœâL¦ä¨ËFTûÏåŲòÙgo„Sèšiìô¡S°%ÿ{¤°:.*!grub_cmd: terminal_input console ^ Gõ4± ÖŠRU@æ þ×É0“J#'Ÿ¡w£˜‘ͯlÍ"¼ÌéjÍÑ ¤}T"ï "F¥[Äæö æôªÜ ]^€ºÎz´€¬“ &Ñu²æ‹£ iL"grub_cmd: terminal_output console ºE+ð ˆ(³]é‰À…8 ‚¤¡NC¤÷a®c(] ðZñ9ò`úå{, szó8+ ®aÄ[<%Èœê?}ÞädŽw`†÷Ö/´¹ÁÕaH¡¾¿Þj9SDV{SŒmðmžgrub_cmd: [ = 1 ] õ°gåœ?g±›ƒo¾é複¡œÝ Eh6·X1¤-dZµ40/¹÷B­ª7·ýáR!]iâYû ±øÐ6®ý2ÎwêBn{=®ãxÝy®Ú–;,S‰‡‡–,éêåWÌéJgrub_cmd: [ xy = xy ] Xy^…’Ùÿ;k9­ÖÛ©XïõG¢ aÊ¥OÂK¨³ç›æ?7Zót$NNÞŽ `€ £ú_» ŸvͧoØ.KE %ƒW§F.§Þä7zÐÙKHŸ}‹DçˆeBõÜŠñV#grub_cmd: set timeout_style=hidden 1¸æBþ“aïY™mµ'‚O" Íõ“¦ªªë•rC»Ž'ÙoLrnÅ#Í8)‚½ñúõM œE+¥¹¦LŽØÌ’·æœvÀÿéŸÀó‰@õ@´e¸kUh…ëZÌéñlï grub_cmd: set timeout=0.1 UÏÖF>ó4«¶´€€³>Àc©ÀQë ϤgoþuGçzf 3µ›>í4Ù³£Ò`‘«Y “J¯Éœ°§ËøÂ^DBF4Š* NîøÜĦ8†Êil­E‘=9"¹§òdºxð.€ \›f‚)ìÿ—,Lņ±M˜p4grub_cmd: set menu_color_highlight=black/light-gray ðêŽ~”ÁÞh.Ól6|ŽÈ¡ûÙ Ø’üEq›sc¸òC¨«·W}³6ge2‡f üÂLE¢ Ò€õ’fr¤¸ñ…Ï«)Û‚óõj¡$Êdåq ÔW†K?@’JýSE.ã}¯<grub_cmd: set partuuid=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f B2‡¤ ‘Kµ—Û2ùf—Ñûž ð´³Â1‚Ž¢úJ,üåïÉÑ^™ÿ¹ÆsIÁ07A¯ zZÀyo¨/Núˆ¶!9…²ØxæIˆj™XvfÏ…ÅôwŠ£Ï„•,¦ÊÓó…SËgrub_cmd: [ != 1 ] ),ÎÒŽ6¨éèT ›ðãË6‘ ]ˆNRÐá‘Ø‚wǨS¨š-„GCÈ釴tØñÇæ ¥à|ü–qvk›¸8sÆÿKí}û¹'Õ°'=*ë¹0Û¤c 7 u ’Û×ÅI_¯§E>Ð7grub_cmd: [ -e (hd0,gpt1)/boot/grub/gfxblacklist.txt ] ‹Ó·zd}¹ˆ¶±êüi`ªE õå6]n—d”6,ƒâè€|ï¡OÔ¬f 2Q îÕTHˆ,»Ý¨ðFˆFY° grub_cmd: export linux_gfx_mode Ïdëuëå\µB¯Bï G¸b€ W}·4`áÛ2ãÜSt»‰slù9twÜÁäÔúÑbY º>˜‘ SM©Ñ‡(`8äaÇAe§ÿaâ.žøÿÜ• 2þ½6’-møíˆgrub_cmd: menuentry Ubuntu --class ubuntu --class gnu-linux --class gnu --class os --id gnulinux-simple-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a { recordfail load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi if [ "${initrdfail}" = 1 ]; then echo 'GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 initrd /boot/initrd.img-5.11.0-1008-gcp else echo 'GRUB_FORCE_PARTUUID set, attempting initrdless boot.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 fi initrdfail } ¯md Q T¬¹ºâ EüOÝžªOö SVã$ºv 3ùd&þȪ…lI`µ@­/Õ7@0cæB „ÛÓ0'D~5²ªEY쨵]Y´Ë¸aœ^iË7—„±Ç•X#ê Ìa@k5ŸŸ]´«Ngrub_cmd: submenu Advanced options for Ubuntu --id gnulinux-advanced-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a { menuentry 'Ubuntu, with Linux 5.11.0-1008-gcp' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.11.0-1008-gcp-advanced-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { recordfail load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi echo 'Loading Linux 5.11.0-1008-gcp ...' if [ "${initrdfail}" = 1 ]; then echo 'GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.11.0-1008-gcp else echo 'GRUB_FORCE_PARTUUID set, attempting initrdless boot.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 fi initrdfail } menuentry 'Ubuntu, with Linux 5.11.0-1008-gcp (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.11.0-1008-gcp-recovery-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { recordfail load_video insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi echo 'Loading Linux 5.11.0-1008-gcp ...' if [ "${initrdfail}" = 1 ]; then echo 'GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.11.0-1008-gcp else echo 'GRUB_FORCE_PARTUUID set, attempting initrdless boot.' linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 panic=-1 fi initrdfail } menuentry 'Ubuntu, with Linux 5.11.0-1007-gcp' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.11.0-1007-gcp-advanced-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { recordfail load_video gfxmode $linux_gfx_mode insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi echo 'Loading Linux 5.11.0-1007-gcp ...' if [ "${initrdfail}" = 1 ]; then echo 'GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.' linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.11.0-1007-gcp else echo 'GRUB_FORCE_PARTUUID set, attempting initrdless boot.' linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 fi initrdfail } menuentry 'Ubuntu, with Linux 5.11.0-1007-gcp (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.11.0-1007-gcp-recovery-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { recordfail load_video insmod gzio if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi echo 'Loading Linux 5.11.0-1007-gcp ...' if [ "${initrdfail}" = 1 ]; then echo 'GRUB_FORCE_PARTUUID set, initrdless boot failed. Attempting with initrd.' linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 echo 'Loading initial ramdisk ...' initrd /boot/initrd.img-5.11.0-1007-gcp else echo 'GRUB_FORCE_PARTUUID set, attempting initrdless boot.' linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 panic=-1 fi initrdfail } } ]e¸Õ.@ݧÐZÈ î[± ^Û@^%íÃ!2£Í³Ü&H5Ý+vꔄ„9,« tÍ”ìÔøU†y¥îAžÏG¤N  IA]¥„¼Áþφ`00 ̸‚xY‹Ígrub_cmd: menuentry Ubuntu 21.04 (21.04) (on /dev/sda1) --class ubuntu --class gnu-linux --class gnu --class os --id osprober-gnulinux-simple-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a { insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 initrd /boot/initrd.img-5.11.0-1007-gcp } öø´Ó¯e÷PžŸÀ“VÛ45•ÿ ƒôõõB¹$e±&uT?æ˜AÅýXF«ÆùGa¾AQO¹€ N*O×ò ¯’Rè⽪µ› øe®V»©¢ˆRï¦eT#¶Ö œ$S„ `G grub_cmd: submenu Advanced options for Ubuntu 21.04 (21.04) (on /dev/sda1) --id osprober-gnulinux-advanced-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a { menuentry 'Ubuntu (on /dev/sda1)' --class gnu-linux --class gnu --class os $menuentry_id_option 'osprober-gnulinux-/boot/vmlinuz-5.11.0-1007-gcp--c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 initrd /boot/initrd.img-5.11.0-1007-gcp } menuentry 'Ubuntu, with Linux 5.11.0-1007-gcp (on /dev/sda1)' --class gnu-linux --class gnu --class os $menuentry_id_option 'osprober-gnulinux-/boot/vmlinuz-5.11.0-1007-gcp--c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 initrd /boot/initrd.img-5.11.0-1007-gcp } menuentry 'Ubuntu, with Linux 5.11.0-1007-gcp (recovery mode) (on /dev/sda1)' --class gnu-linux --class gnu --class os $menuentry_id_option 'osprober-gnulinux-/boot/vmlinuz-5.11.0-1007-gcp-root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 panic=-1-c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a' { insmod part_gpt insmod ext2 set root='hd0,gpt1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a else search --no-floppy --fs-uuid --set=root c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a fi linux /boot/vmlinuz-5.11.0-1007-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro recovery nomodeset dis_ucode_ldr scsi_mod.use_blk_mq=Y ima_hash=sha256 panic=-1 initrd /boot/initrd.img-5.11.0-1007-gcp } } Å +#LªAn÷Á–«N’¸à Vƒ˜Ï.Jõˆu»×ÿàXìE¾ tQ/©¢þ}´¦ %Àؼߴ sÎ( ¸XœD°¸%÷·ùýTXV±°:Þò‹n°CàÊijrž )æ&!grub_cmd: set timeout_style=menu è³tJÙGðu‹D†ToxýnZ_­T "sLø`:¼ÛuøÎF1äÁØówwŠD+Ìòíà»hî óiN$O!“Á“²/]%*­ö€ ×Z™ ’*I'ödžƒÏ4äÔ»×";¥›:grub_cmd: [ 0.1 = 0 ] =¸FÓׄ M¬¸c–¤"ÌÔÓ qlã5v To­˜ h¹«d¹à PòÂÚN½Û}>¾¥Y à :“Wò†zäfüðÕÒ3Lj„f 4•ÍÉè–.‡cŸØÏAÉNŠH„áš+Áá1grub_cmd: [ -f (hd0,gpt1)/boot/grub/custom.cfg ] £2móBW^Qù¡ÈÕÑzïòÐ ÕGWX1¿oósƒ°·Žy #r£¦zÐÑÊ5Û û³†EHa±º§zaWm4,'ÀÐ%—d˜%ÎäLöX¯+ تI–ák›l2±ã;´Lgrub_cmd: [ -z (hd0,gpt1)/boot/grub -a -f (hd0,gpt1)/boot/grub/custom.cfg ] ÇjeëÚj£Ú«¼ÖH;ð ô ¿]¤fÀ÷x™ ÜÈú,Eaº’‘-_¼JÁãû £ {äû›ë‹"‚ÿФ~±6G&(Ô(KÙ®ŽŠt¨á_ „´cm·i*J`Ìgrub_cmd: setparams Ubuntu ˜ÐføÿÐFºË8±Œ¾é­§) ¥~~(nüNê‰e@ñ:8Ì’ä'{í‚ ígL”¿.­ °»…ÿxŸ%ÝcãAsk”ô¿:Íÿö ÓÿÊW‰ës}(£šömäf@Kû» Ú×grub_cmd: recordfail ºÁp…þõ6b¥ ï¿6hDÀtÿ d½¨ö[…׆‚H¢’ÄIf È÷PuÁ ‡®Y¤Û@á ³SϘ3›é«­ñ€Ø:¾µîîÀC³ò$v»]°º/Ca & óF ì³Á$í© l§¢grub_cmd: set recordfail=1 UÏÖF>ó4«¶´€€³>Àc©ÀQë ϤgoþuGçzf 3µ›>í4Ù³£Ò`‘«Y “J¯Éœ°§ËøwíEìüqHàÉ4ÐRk(&Å|“€,Éb<%’6‰Þ/ËbfŸãáágrub_cmd: [ -z ] ’^æ›|ŠÄ“|¾GÕÈSQØi´è× Î,Âwº;Ç[f!cëãp4MK®×_µ½@¶ºß .GÅä›óÉ4ôˆüÀsH•P¦M¶* | DÉÝœ*ù7d|‡½wã8>pž úgrub_cmd: save_env recordfail åžfÖì„ G$÷‘é)ñSáD v&«Ø¾tBÂåu6J>•Ë:;S»á†<ךæk eÍéŒû ‰q˜jˆÍøgrub_cmd: gfxmode keep .gmÝ›ð× Í\fØW2Þ{w¶ ¥‹wÏœIÀ¹yßgçòÁ“Óa>?ÄÉ똢µÐoÌ |^¡± ¦’ $á-µö¥°ënÓfÌëŠËDx…rB"õc#¤“ѳ©Xú|grub_cmd: set gfxpayload=keep RAµß¥†y‰]•÷Ÿú _BºKUê µ]„»° ^»ÆÊÝjœ´›5¿ÌlNùÅ;f ÷ÇDY» ø®$‘X‡œʳ¸¯”^ ÷±iw½e¨ \ˆÿ)Ëvó½Ögrub_cmd: [ keep = keep ] ˆn*¡™ôöÒ™~ Šèk ÏÐ;6èoaq"çóÿèŸ|ðú§sñ¼í(÷ðÁú ‹ÈèÅaòYˆ¾žiÚ*ö&ÇÓÇ5õ™«Ï'ø<S §hGÜ^I/Az$²ôW&grub_cmd: set vt_handoff=vt.handoff=7 ºPœ£‚ðhû lFtÔÆRîg¹Šb×TËòÕÜ ÚãÖn‚ǔė„ †*ç—aS$ý\=ûü²&9b…^ÒÛ)iù„VðÚ¶ªŠ¢âþ¼g)W†¨çê¤^6Í£úóÐ¥õü’ìM$ïJÙXFiY4¶Â² åkå+Ûâ÷Oûgrub_cmd: insmod part_gpt ¯?«¬ž\V¸/ «˜2‰ª»öï ¸8¤Ò† û±z·ö eY ›; ›1ØÒû áB¥”Ùˆý¥¦[$¤¤Œ,ô°6ÝwJ♯E·Ó; þ¤©iÓÀÚrºSùîê÷¦grub_cmd: insmod ext2 Ëñ¼³÷, M°Ò~énʪš0Ê ûͼÑÌsõÿYO‹!ìÖõÖ*ÒòÚ/·¼ÇX‡ÁL2ÑbÅ<ɨARÕ-ŸöŽgrub_cmd: set root=hd0,gpt1 õ°gåœ?g±›ƒo¾é複¡œÝ Eh6·X1¤-dZµ40/¹÷B­ª7·ýáR!]iâYû ±øÐ6®ý2ÎwêBn{=®ãxÝy®Ú–;,S‰‡‡–,éêåWÌéJgrub_cmd: [ xy = xy ] ÙÙÞiûO‰aÊÂö¯¥ðz7 Ln?=š•šBßzáNf_À¯ ÅAyúF T7’f DÙ­Q%ÐùÌmZý–j«.-Ä™œVñòlßZ¼ÓihJ³Ȇf.¶‘]–œgrub_cmd: search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1 c73d8355-1ac9-41b4-8edf-c1c1a9d5bd6a ºE+ð ˆ(³]é‰À…8 ‚¤¡NC¤÷a®c(] ðZñ9ò`úå{, szó8+ ®aÄ[<%Èœê?}ÞädŽw`†÷Ö/´¹ÁÕaH¡¾¿Þj9SDV{SŒmðmžgrub_cmd: [ = 1 ] T –‚-†@ÏeOc~º—Réâ Ñ»×ÕsÖ6… žûϬžXŸÍ4ö±kLJ"uêl= !dÙFâ|îщŒ~Øv™))c¹-@Øê0…´2„¥{?=ûƒ¬ Eë(®pÝ_ýQ„Dgrub_cmd: echo GRUB_FORCE_PARTUUID set, attempting initrdless boot. §"RøÄ¨3-ñbçÍ8þî>Oó {5ð‹ÿ.H¡µ:eØ™¡Ä5¤2H‹ÂŽ7c™fGzð®*² Ã\*ýê»ã¬ôÞí_udðÆ6W4 +™Œ“Îg\ÃçXôÈ«\¤Ôßó¡grub_cmd: linux /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 öUŠ]<|U¸/'‘$£rY‘øV< 8Æ9n· „®ñ?8J7·ç¿§zã½æ2§l¬¶\—  „PÔnãM·Û@8$Òåy$”Ÿ*ÚxhL›&fìG)ÄÀæ˜@ºÙ!ß"{¡C/boot/vmlinuz-5.11.0-1008-gcp ÁŽÊZîƒæt‡‘‘XO´[— Ÿ V ްdTÉkc ‚s÷… ëã ãçéÉ+ðäYmL ,TN·Ò$šháÍ ¬¯áË‹mˆ\$@^?9 œfžlRmÿÄ¡ÙE˜ŒL¡kernel_cmdline: /boot/vmlinuz-5.11.0-1008-gcp root=PARTUUID=bf817bdf-6a3a-4221-8edb-2c1ca7c5537f ro scsi_mod.use_blk_mq=Y ima_hash=sha256 console=ttyS0 panic=-1 ŒiDÅퟄ?Õõ¼2”çÛ v¼lmpÎ4¢KÚ&5„íÐý]”ù ¢Ý^P é‹=ò sÕü÷ucÔ*³k1Ú€ G˜sä8>ÂØBŽÕrúBžÌûÖ>¿}4+¡š~è(í3Ó•grub_cmd: initrdfail UÏÖF>ó4«¶´€€³>Àc©ÀQë ϤgoþuGçzf 3µ›>í4Ù³£Ò`‘«Y “J¯Éœ°§ËøwíEìüqHàÉ4ÐRk(&Å|“€,Éb<%’6‰Þ/ËbfŸãáágrub_cmd: [ -z ] p&‰ ü¨4˜9Ü·‘=ÈKÕ{Ñ k,—ö@ºØsÈ¡4G’®þ;©>Øò ¸è‘“Rlÿ_» É2 }ú‹ /¿àéRâ¿ ˜G‹²xç‹2è¯_/ÊÞö‚âòèO'›«N"²grub_cmd: set initrdfail=1 z†Áò8gØ•¹Tqa‹Þ- $6¯ãËT«€}l¥&í12ÜYxžÓòñHèiHéx L÷&ìÔ"µm÷Ê/7|²¤îmœ¡õ´@–øüf·;VÐïü91Å©3'QrË÷grub_cmd: [ -n ] ŸP–{Àf‚iDj©/+ˆb  X9ý›þ¾;Þw9ßjƒ 7âZGÿ¦¡d´¢ PÈ &%Ðýô` , ™>¹`ɸ­*Í0™ê#ë?êX³&=Ù‰UóJ¨”Ž4èd·G ­grub_cmd: save_env initrdfail€D:k{‚·¯VO.9<ÙÕ£ˆ·úJ˜ Ø=k{…­5޳¶®j‡:·ï#¢cRÅÜOªZîÚÏ^´ !K ïyu`4Hwt?Ü*S‚ºÆçbÖ$ÌóöT@|K­÷Øù)]ÓÚ½ïe²vwàExit Boot Services Invocation€GUEÝÉx׿Ð6úÌ~.˜HŸ µOuBËØr¨ꃛ+t|~½^¦a\@ô/D¦Ûë  .È]êç¥0­Œm ¨@ º¾l‰‰&ž• Œô@Æé—i^dÔUÄJe,Ѐö# t(Exit Boot Services Returned with Successtpm2-tools-5.2/test/integration/fixtures/event-postcode.bin000066400000000000000000000706441412464516500242270ustar00rootroot00000000000000%Spec ID Event03 Ä/í­&‚ËùxAÃDç®3 Ôr @ C‚¸V€ù ?kꊴ}(=³+n«í»ñUûkT U@¤­Nô¿¸:*ã8@z=“è#`é‰Á+‰è8¦ S:pk,2¬;B4)YÔÿa5ëéÞRì´°à€L:íËäÿð§€ÔýÑñM@AIMëÉÄSCÒ'} ÌüK³(ˆ£E¼ŠêÚºU+b}™4Œvv«1Aõ°@¤5aßä‹Ê“Òª à˜+Œ SecureBoot€tiR Û´ „ ñ´™¦¬r9b ±aà4_ —ùõ&BÔ;:‡¹†Úè×vÖ¯'æF†uæóaßä‹Ê“Òª à˜+ŒÏPK¡YÀ¥ä”§J‡µ«\+ðrϳQHÜ&_áJšûøƒ»³^0‚Ÿ0‚‡ ;˜ÇOÑ©LCƒ6=ÎÔ…0  *†H†÷  0r1 0 UUSA1 0 U CA10U San Jose1"0 U Super Micro Computer Inc.10U SUPERMICRO PK CA 20180 181220014604Z 331220015603Z0r1 0 UUSA1 0 U CA10U San Jose1"0 U Super Micro Computer Inc.10U SUPERMICRO PK CA 20180‚"0  *†H†÷ ‚0‚ ‚³˜¿íÀiQŽMª‘)Î1žbŽ*ä'ÚΕêâ4¹ó]_A®ö+eR7+­juúî‡ÖxWUÅy˜n96¤ëiîç3[Âðùå–ûÇî!ÛAõ¤Šbƒ£Ë«t, XbrÐùâÉ[1vêYº7ä;ÊX±ù¦ËqŒ¹"iH?sWcÕÊT鮉K–*1ú3Va[ø }øMÛų́re•¢Ë`(Ü [r:œeƒH"$I‰0´ 󞯽[“·MìJ´oå¤5áõxA` }üyÞCùéÞ"Íbwu›À}æ|«‡Œ÷¹xg†—Ä~,2ò¢sÖPËÄF©:ª:a`4ÅŒë¶Ï «{ü°Ø¥‚Ý©—eàŽbLª%*ýf]íÚNGÂÕüiñª¦³-fàç ˜b? ,fSU©‡û¿_GLŠøÑ=‡ÀÿÆNóš™^QŸ½„ðvà—;Œð8kKÊü³¸²Ã€ð/¼sƒí|‰~ 2ö8â‚l cÀîxëI¹Â°7h¨'ëù±#pöXQ±šˆ;ó.¯*>aßä‹Ê“Òª à˜+ŒKEK¡YÀ¥ä”§J‡µ«\+ðrü½šúwY2M½`(ôçxK0‚è0‚Р a ш0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110624204129Z 260624205129Z0€1 0 UUS10U Washington10URedmond10U Microsoft Corporation1*0(U!Microsoft Corporation KEK CA 20110‚"0  *†H†÷ ‚0‚ ‚Ä赊¿­W&°&ÃêçûWzD] ÚJåt*æ°ìmëì¹ãZc2|Oã §8“ŽÆõà„±š›,çõ·‘Ö áâÀ¨¬0ßHóPšd§QÈ…O †Îþ/áŸÿ‚ÀíéÍÎôSjb: C¹â%ýþùÔÄ«â#‰p·¤Mì®åœúÂ×ÁËÔèÄ/å™î$‹ìò‹êÃJûC ~µG’lÜæ‰ëõ3ë*qåùƒ<ÿ% /hvFÿºO¾Ü­q*XªûÒy=ä›e;Ì)*ŸürY¢ë®’ïö5€Æìä_ÌvÍïc’Á¯y@„y‡ãR¨è{i£‚O0‚K0 +‚70UbüCÍ >¤ËgÒ[ÙU¬{̶Š_0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚Ô„ˆõ”Ê*<û*’ × ÑñèRf¨î¢µuzª-¤vZêy·¹7jQ{döádòg¾÷¨x½ºÎˆXd ÖWÈ£_ÖÛÆÐiÎHK2·ë]Ò0õÀõ¸ºx£+þ›Û4V„ì‚Ê®A%pœkéþ×–å甲* Kÿ(){÷×|¥Ñv¹Èyí’œÂþßo~l{ÔÁEÝ4Q–9å^VØ–ô¦B³ wýòqVÌŸ†#¤‡Ë¦ýX~Ôig‘~òå ‹Š<‡„ëãνCå­-„“Žj+Z|DúRªÈ-»àRßøš=Á`°á3µ£ˆÑe ç¬|¤Á‚‡N8±/ Ňoý.¼9¶çæÃàäÍ'„ï”Bï)‹FA;gØùCYeË ¼ý’Oôu;§©$üPA@yà-O j'vnRí–i{¯÷‡ÐE­Sû0ª76aÚJi4ØhíÖÏl” ÓÏl"y­±ð¼¢F`©ÄÂ!‚ñýòèy2`¿Ø¬¥"KÊÁØKë}?W5²æOu´°`"S®‘yÖ›A†Tp²Þ 5|°4rº—`;ðy뢲]¢¸‡Åéöµ—%o8Ÿã‘úŠy˜Ãi·£ —øÊ®×ÄóÀuk4 µ™`ó\°ÅWN6Ò2„¿ž€°£0x9(C§Ükk÷¬ë;ú § W ›×út¢gÂþ^USÆÈ2Ó0ÿú¡,3#Æ `Hg˲×:=–E£¼ÚÐgeoCdb¡YÀ¥ä”§J‡µ«\+ðr@$½šúwY2M½`(ôçxK0‚0‚ø  aÓÄ0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110627212245Z 260627213245Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U"Microsoft Corporation UEFI CA 20110‚"0  *†H†÷ ‚0‚ ‚¥lLÇE jK ¤À‡u CTdàí’} ²s¿ ÆJEa Å-–Óõ+ ûMI›A€<¹Týæ¼ÑĤŠAŠ\Yƒh2»ŒGÉîq¼!OšŠ|ÿD?2²&H®uµîÉLJ~䂚xwM °½öÓÓ¼ú+¥Q8]õûºÛxÛÿì –Õƒ¸é¶À{@{á('ÉúïV^æ~”~ÀðD²y9åÚ²b‹M¿8pâh$É3¤7ÕXi^Ó|íÁSçN°*‡caocYê²+y× agŠ[ý^­‡º†gOqX"""΋ïTqÎP5Xv•îj±¢Õ£‚v0‚r0 +‚70# +‚7øÁk·wSJó%7N¡&{ p€0U­¿C ½‚pœŒÕO1nÕ"˜ŠÔ0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚5Bÿ0ÌÎ÷v ­hX5)F2v'|ïA'BJªm8HYUóéX4¦ ‚ª]­‚Ú€ƒA´ò¹ó]ñPù³U„B( ½²®QÅÀ¬—•!Ûüwž•s‘ˆÊ½½R¹P ßWž aí åm%Ù@@ÈΣJÂM¯šT½Ç¼¹+=I+2üj!iO›È~B4ü6‹ @À³š%u'ÍÉ£ö]Ñç6Tz¹PµÓÑ¿»tßÜ€Õíô/k/ÞfŒ°#åÇ„ØíêÁ3‚­VK-ñh•ÍÏðrð®»Ý†…˜,!L3+ðJðh‡µ’U2u¡j‚j<£%¤í­×®ËØ@Y „Ñ•Lb‘"tŒ=GD¦ä°›45±ú¶S¨,ì¤qȸºèDfäGTŽV³Ÿ˜²†Ðh>#µ/^P…Æ‚_A¡ô. à™Òluä¶iµ!†úÑöâMÑÚ­,wS%27ÇlRr•†°ñ5ajõ²;PV¦2-þ¢‰ùB†'U¡‚ÊZ›ø0˜T¦G–%/È&äA”\?å–ã…[<>?»GrUâ%"±Ù{ç*£÷Fà Ö‰ã5'bq¦ïÐ'  Y7`ø8”¸àxpøºL†‡”öà®Eîe¶£~iu’›õ¦¼YƒX¡YÀ¥ä”§J‡µ«\+ðr뽚úwY2M½`(ôçxK0‚×0‚¿  avV0  *†H†÷  0ˆ1 0 UUS10U Washington10URedmond10U Microsoft Corporation1200U)Microsoft Root Certificate Authority 20100 111019184142Z 261019185142Z0„1 0 UUS10U Washington10URedmond10U Microsoft Corporation1.0,U%Microsoft Windows Production PCA 20110‚"0  *†H†÷ ‚0‚ ‚Ý »¢ä. ãçÅ÷–i¼!½i33ï­ËT€îƒ»Å „Ù÷Ò‹ó8°«¤­-|byÿãJ?5 pãÄçkàœÀ6uéŠ1ÝpåÜ7µtF–([‡`#,¿ÜG¥g÷Q'žrë¦É¹;S5|åÓì'¹‡þ¹É# o¨F‘Án–http://www.microsoft.com/pki/certs/MicRooCerAut_2010-06-23.crt0  *†H†÷  ‚ü|qQ¥yÂn²ï9>¼«\`ìß¨Ó éôö–…¶QˆfG¢°=*hw»‘Lb{¶ÁǺz‡4Kbz™éÊüÎJ7É-¤W|þ=ܸZúÖij…:ê³Ùnäi!7ÞÑöugÓ“W^)9Èî-áÍäEs[ÐÒÎz«‚FXÐ^³g¯l5ò¼å?$â5¢ uöV™Ôx,ÑëЈªñߺ~,c·›#!ÄùxlâX6+‘̤Ùò-ºù”@íEñΊ\k>«Óp* jà_GÑÕc 2ò¯×6*pZåBYqKWº~ƒð!<ôÁŹ“ˆE“†é± ™¾˜ËÅ•¤]bÖ c ½uw}=óE¹Ÿ—ŸËW€o3©Ïw¤bY~¡YÀ¥ä”§J‡µ«\+ðr–zQHÜ&_áJšûøƒ»³^0‚f0‚N 0  *†H†÷  0r1 0 UUSA1 0 U CA10U San Jose1"0 U Super Micro Computer Inc.10U SUPERMICRO PK CA 20180 181219000000Z 331219000000Z0w1 0 UUSA1 0 U CA10U San Jose1"0 U Super Micro Computer Inc.1#0!U SUPERMICRO Product CA 20180‚"0  *†H†÷ ‚0‚ ‚ñÊM4j›m?XRççÚáÊ0ž¨ÄO jàiM=59äY-CÙ( Üp3¢‡"®é’ÐÛæ¥Ÿ¯t£›3î¡Òƒš•Œ EöµJù/ÉPìì èåno¸ðвî;œÇFû²WñGž&Wêíè9u@ `CÝì[Ò8–}içÓ­9ìëôU—b!¥)¿¾ßbì[l…A«?PUJÞáЧ‹”ͳ5ÆçÞ† ?s)g0Î{.•Æã“ €÷”ª`yö KžñÓ?ÌBrVÒ˜)Áþú^8¥W¦cóh¥ÙõõSíþÑö†S >!¢|o€£00  *†H†÷  ‚6]ÉÀõh'8ËÀ.'›Q—XIØú!¬{ÂÀ¿úÕ{¹ÈÊTe)!FüH}úó„[d}†q–N»Ž¥œËeDbì̺B¶‹Ø¤Û˜&šä§ ÚÉ;€Ócd¡|ÂéÞôò×@gåº×mnÂ5_Û«]Žà¡Ò%ª©o1Ã¥Àèò£³GZiX8:§»dÌi'¢Är•á~Té[é Ýq­ÿ´°´( H\)”*Xš/·b>>86AH0'd'V¡!Úb³ïÀ˾gÜÈfò¯LCI#‰ÇbÆj¯šŒê×Fs;0²©ü°sÓ;|Çy‡+Ì”˜¬0 %Ÿã¡YÀ¥ä”§J‡µ«\+ðrfJQHÜ&_áJšûøƒ»³^0‚60‚ 0  *†H†÷ 0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root0 000530104838Z 200530104838Z0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root0‚"0  *†H†÷ ‚0‚ ‚·÷3æò-9àN[í¼l͵ú#¶ÎÞ›3—¤)L}“Ÿ½J¼“íãÏåmPZÖ—)”Z€°IzÛ.•ý¸Ê¿78->‘A­pVÇðO?è2žtÊÈTéÆ_xš@<¬aª^ž‡¡jPÜךN¯³¦q”œq³P` Ç8†¨é¨i&«L°O#«:O„ØßΟáio»×B×kDäÇ­îmA_rZq7³ye¤Y ”7÷/ Â’rÚÐ8rÛ¨EÄ]*}·´ÖÄî¬ÍD·É+ÝC%úa¹ijX#·§3VuYõÍ)×F· +e¶ÓBo²¸{ûïé]SÕ4Z'£Ü0Ù0U­½˜z4´&÷úÄ&Tï½à$ËT0 U0Uÿ0ÿ0™U#‘0Ž€­½˜z4´&÷úÄ&Tï½à$ËT¡s¤q0o1 0 USE10U  AddTrust AB1&0$U AddTrust External TTP Network1"0 UAddTrust External CA Root‚0  *†H†÷ ‚°›à…%ÂÖ#â–’A˜œÙ„yÙ[#6e°Øw»¬AlG`ƒQ°ù2=çüö&Ç€¥¿Zü‡Ïxy‰!šâL †5¼òÞQÄÒ–·Ü~Nîpý9ë Q-޽àÁßFuç$­ìôB´…“pgº5JÓ+zÌQB¡zcÑæ»¡Å+Â6¾ æ½c~y{§ @«jÝŠÃööŒBQÔEõŸ§b!h C<™ç|½$Ø©‘sˆ?V18´qšÍÈžŽ.ጘƒË1ñDLÆsIv`Çø½€k.éÌLZšy .Õžc&U’”Ø‚Z{мÇN†€ž¶ƒ±­çBpÜ`ƒÝqjÌc£3  D´ÎJMÊšóÈ—ÜVî'Ã…ëˆ÷Ϲ +‚e[²˲×:=–E£¼ÚÐgeoŒdbx&ÄÁLP’@¬©Aù6“C(Œ0½šúwY2M½`(ôçxK€´Ùi1¿ ý‘¦ÑO¤Ræm²@Œ¨`MA’eŸ ½šúwY2M½`(ôçxKõ/ƒ£úœûÖ’r($ÛäE4Ò[…$k;•}¬nÎz½šúwY2M½`(ôçxKÅÙØ¡†âÈ- ¯ª*o.s‡ >d÷,Nïgyj„½½šúwY2M½`(ôçxK63„ÑM. xbd„ÄY­W£ïC–&`HÐXÅ¡›¿v½šúwY2M½`(ôçxK세Kle¥ ©¾q–R0! bÖÓ h2Û²Ò à'%'ß¶=IÒ•r¦ôL½šúwY2M½`(ôçxK^ê‰T‹ `²þíÚ< Çþ›Ík”覃¸R8½šúwY2M½`(ôçxKæÆ¨Xdo±ïÆyþ(±#gþ’æ¾+6™žÿ9О½šúwY2M½`(ôçxK ß_NQìx¹mÐ%ý¶†ãŸor’xRY›eœ&½šúwY2M½`(ôçxK »C’Ú¬z¸›0¤¬eu1¹{ú«ù ¯åù¶ë ct½šúwY2M½`(ôçxK “9v-ó6«=ФcßqZ9ϰô’F\`lk×½‰Œ½šúwY2M½`(ôçxK ¾Êo)ì o3}räˆK ³H˜:* ×?O½šúwY2M½`(ôçxK Éóû™–!HÃʃ62u>Ôü ¹[1æR*Í[ü½šúwY2M½`(ôçxKo¬êÏìýN0;tô€ €˜âЀ+“oŽÇtÎ!ó†hœ½šúwY2M½`(ôçxKN: [CƦ»Ó@O4=Ï9bgΔøµ.#©Ú’ ½šúwY2M½`(ôçxK34)ÿbퟗ>HÜîå-¾.ImTµÏÖÈdÒѽšúwY2M½`(ôçxK+™Ï&B.’þ6_¿Kà 'lžáKzoÿDû/ki™9½šúwY2M½`(ôçxK+¿,§¸ñÙ'îR¶û*]ÐI¸Z+›Rœ]fb°Uø½šúwY2M½`(ôçxK,sÙ3%ºmËå‰Ô¤Æ<[“UYï’ûðPíPÄâRñ}½šúwY2M½`(ôçxK.p‘g†¦÷sQ§«pµWÆ2.©#²¨Ó¹+Q¯}½šúwY2M½`(ôçxK0f(úTw0W(ºJF}çÐ8zTõiÓvŸÎ^uì‰Ò“½šúwY2M½`(ôçxK6íºõ­A¤¡wz¿/¯^g4g^Ù^i5‚ž ªÒ½šúwY2M½`(ôçxK8AÒ!6ƒ×\ æ!`9MlN g`¶ö¹b¼…[½šúwY2M½`(ôçxK?ΛŸß>ðTR°ù^ä·ðmt:syqUŽpjÎ>s½šúwY2M½`(ôçxKC—Úʃžc|µ ’ßC¼-/²¨õŸ&üzKÔÙu’½šúwY2M½`(ôçxKGÌa'⚆à:kï,ÔøÅZmkÛ6!hÃ,ã*Zß½šúwY2M½`(ôçxKQˆ1þs‚µÐ>Æ!"‹Š¶Ty½ ¿£ÅÁÐôœ0a5½šúwY2M½`(ôçxKZéIêˆUë“ä9ÛÆ[Ú.B…,/ßg‰úg6ãÃA+\½šúwY2M½`(ôçxKk€xäAЦë{³^`’ÏGžëŒäÍçÐrÌ´/f½šúwY2M½`(ôçxKlˆTGÕYâ“Q¸&Àl¸¿ï+”­585‡rÑ“ø.ÑʽšúwY2M½`(ôçxKo(ÿqÉÛÕ¯.{¿Ë«d|ÂeÝõ²“Ͷ&õ :x^½šúwY2M½`(ôçxKqòoÒ"I~T£Fb«$—üÈ wõhéãÙ¿Ëýcu½šúwY2M½`(ôçxKrk>¶Tj0óø=›–Îöpé¨ÑpŠqæ-Ä,#Á½šúwY2M½`(ôçxKrà½gÏ]V«Šß;ݼ‚¿2¨ØªŒ^/mò”(ÖØ½šúwY2M½`(ôçxKx'¯™6,úðq}­ä±¿àCŠÑqÁZÝÂH·[øÊ¤K²Å½šúwY2M½`(ôçxK¨¹e»„Ó‡k”)©TÌ•SϪØÈ£;ý3ÿð佚úwY2M½`(ôçxK‚Û;δöCΗÃч͛YAÍ=èXo+ÚV7W_g½šúwY2M½`(ôçxK‰Z—…öÊ~ÔOÁ¡G qóñ"8bÙÿÌ:âß’=¯½šúwY2M½`(ôçxKŠÖHYñ•µõ¯ª” jag¬ÖzˆnF“dr!ÅYE¹½šúwY2M½`(ôçxK‹ô4´žÌ÷¢ÍeËì;= <5¾P_ß{Õcõ!½šúwY2M½`(ôçxKŽ¢‰Ïç «seË(îQíÓ<òPmèˆû­Ö¿€H½šúwY2M½`(ôçxK™˜ÓcÄ‘¾½tº¹M’‘soܦC£fd¼1ZB½šúwY2M½`(ôçxKžJi1ah.Uýèþõ`ëˆìþܯfÀÊ÷²·4½šúwY2M½`(ôçxK¦µ6UÓ¢¯ G'Yykä¤ T•§ØiuLHH…t§½šúwY2M½`(ôçxK§ó/PN°þ­š~ùNѺ ì]æ÷ïoð¦+“¾ß]E½šúwY2M½`(ôçxK­h&á”m&Óêóh\ˆÙ}…Þ;MË=â®Ç`ÑùÂ$Q?¼eYW×5ú)õ@νšúwY2M½`(ôçxKØËë—5õg+6~O–ÍÇIia]JélrMBÎøóú½šúwY2M½`(ôçxKé,"ë;VBÖ\ÂÊòGÒYG8„D•oYâ°Ñú½šúwY2M½`(ôçxKýÝn=)ê„Çt=­JÛǵþÁ³‘ù2@†¬ÇÖÛØ½šúwY2M½`(ôçxKþc¨Ox,ÉÓüòÌùüûÐ7`‡‡XÒb…íf›Ünm½šúwY2M½`(ôçxKþϲ2Ñ.™KmH],qgrŠ¥RY„­\¦u"š6½šúwY2M½`(ôçxKÊaJ~“”ŒÐþUÓ™ùÑ©nE AR'ÂÆ[½šúwY2M½`(ôçxKU¹› å=¼þHZ©Ç7Ï?¶ï=‘úµ™ª|«í§cµº½šúwY2M½`(ôçxKwÝ£ ˆÿ^; æb x  S^ˇæðˆŠ k/½šúwY2M½`(ôçxKÈ<±9"­™õ`tFuÝ7̔ܭZ˦G/î4qÙ9脽šúwY2M½`(ôçxK;‡S> ÃÐì¨#Ëð©AªØryÑÄ™€-Ñæ6¸©½šúwY2M½`(ôçxK“šîôõúQâ3@ÃòäHΈrRjý÷Rçó£ò¼Ÿ`I½šúwY2M½`(ôçxKdW[Ùxš.­Vö4R¯kø ùDxYuéðN-d×E½šúwY2M½`(ôçxKEÇÈ®u Ï»Hü7R}dÝdM®Ø‘<ÍŠ$ÉM…igߎiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€Õúøú­PÖ%á¦Gh¿š„1 ^(™i¬€YY}©à—«ðS–’Ëa™ô`œ¨¬T@dP• 4 ÐA 8FÿEÿ€Õúøú­PÖ%á¦Gh¿š„1 ^(™i¬€YY}©à—«ðS–’Ëa™ô`œ¨¬T õcP• 4 ÐA 8FÿEÿ€Õúøú­PÖ%á¦Gh¿š„1 ^(™i¬€YY}©à—«ðS–’Ëa™ô`œ¨¬TðècP• 4 ÐA 8FÿEÿ€Õúøú­PÖ%á¦Gh¿š„1 ^(™i¬€YY}©à—«ðS–’Ëa™ô`œ¨¬T@ÜcP• 4 ÐA 8FÿEÿiÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸iÊxçE (QsC>RÅÂR™äs ß?a˜©/Û@W-Ä=×HêwŠÜR¼IŒè$À¸€?¼ßíT_Š"Ÿ÷«•X8¼s"n ¿,Òâ"°Åø§Œ†”¤®–ƒü‹ñÌLÍÉ\>ÁñRaßä‹Ê“Òª à˜+Œ BootOrder €«#\þÃL¹EÛ7‘–Jûvmc  þ¥Wp‘Ó{ír¨{´ËVgчŽxý·1ª0zjxOrGâ½aßä‹Ê“Òª à˜+ŒBoot0007÷UEFI: PXE IP6 Intel(R) I350 Gigabit Network Connection - 0CC47AFF601C ÐA  % Äzÿ` <@ÿvïGd-É; A¬MQÐLæPXE IP6 Intel(R) I350 Gigabit Network ConnectionÿBO€@yŸ7F"½ÉÜVß7'R2ŒÝ YhiÕ~#_ÇìmjÍÑËÒùì4@Ö³H{Ó$ª¡’½aßä‹Ê“Òª à˜+ŒBoot0008÷UEFI: PXE IP6 Intel(R) I350 Gigabit Network Connection - 0CC47AFF601D ÐA  % Äzÿ` <@ÿvïGd-É; A¬MQÐLæPXE IP6 Intel(R) I350 Gigabit Network ConnectionÿBO€'Ç”o[MþÖÐîÖ@îeÂÊÓ•Á a›<3˜uÝ:!ÄC‘ì –ªd sülT£Ü7cMm½aßä‹Ê“Òª à˜+ŒBoot0009÷UEFI: PXE IP6 Intel(R) I350 Gigabit Network Connection - 0CC47AFF601E ÐA  % Äzÿ` <@ÿvïGd-É; A¬MQÐLæPXE IP6 Intel(R) I350 Gigabit Network ConnectionÿBO€Ÿe’o»^z©Žq„ ú‚"ZØà n¦ °_qwb%Oþú€O8‘“^'¸?ûMB ½aßä‹Ê“Òª à˜+ŒBoot000A÷UEFI: PXE IP6 Intel(R) I350 Gigabit Network Connection - 0CC47AFF601F ÐA  % Äzÿ` <@ÿvïGd-É; A¬MQÐLæPXE IP6 Intel(R) I350 Gigabit Network ConnectionÿBO€C¸™<Ç$®ðÿt&mçô¯ä†šñ ^ï¾q ¸;N?®¥N$KCnüÎæ Â?“<ý¹(¬aßä‹Ê“Òª à˜+Œ|Boot000BÞUEFI: PXE IP4 Mellanox Network Adapter - 98:03:9B:85:13:B2 - 98039B8513B2 ÐA  %˜›…² ÿ~ïGd-É; A¬MQÐLæPXE IP4 Mellanox Network Adapter - 98:03:9B:85:13:B2ÿBO€ ¡Ì@’ ­,â¡¶ YRJã¯ðþ F“”“ìIó䎰4?A÷9e <Šw†—Р% ì:4¬aßä‹Ê“Òª à˜+Œ|Boot000CÞUEFI: PXE IP4 Mellanox Network Adapter - 98:03:9B:85:13:B3 - 98039B8513B3 ÐA  %˜›…³ ÿ~ïGd-É; A¬MQÐLæPXE IP4 Mellanox Network Adapter - 98:03:9B:85:13:B3ÿBO€`þ ðà&Lkëî Äu¥@ò 91O‹Hþå×ìҪѽõµùc¸%3T¾a0“”ëm¬aßä‹Ê“Òª à˜+Œ|Boot000DÞUEFI: PXE IP4 Mellanox Network Adapter - 98:03:9B:84:B3:AE - 98039B84B3AE ÐA  %˜›„³® ÿ~ïGd-É; A¬MQÐLæPXE IP4 Mellanox Network Adapter - 98:03:9B:84:B3:AEÿBO€eÁ…ÈÎ Öô0¥' ¯µº¹Î tÉ$]^¯?c-ß v.°ã/ž}í=êw¶+E¬aßä‹Ê“Òª à˜+Œ|Boot000EÞUEFI: PXE IP4 Mellanox Network Adapter - 98:03:9B:84:B3:AF - 98039B84B3AF ÐA  %˜›„³¯ ÿ~ïGd-É; A¬MQÐLæPXE IP4 Mellanox Network Adapter - 98:03:9B:84:B3:AFÿBO€ðšÇÐö?«·nô,Ë‹3öí¡Œ SŠáõÑ¿L¸i :ôê?NQœrÒÎÇF¶p°·Íaßä‹Ê“Òª à˜+ŒBoot000FÿUEFI: PXE IP6 Mellanox Network Adapter - 98:03:9B:85:13:B2 - 98039B8513B2 ÐA  %˜›…² <@ÿ~ïGd-É; A¬MQÐLæPXE IP6 Mellanox Network Adapter - 98:03:9B:85:13:B2ÿBO€==j³É `£jÿv¹·ßÙ£\ ÄFí®.öA” {s'rFÖ”™vàÎ}›æõšaÈåÆÍaßä‹Ê“Òª à˜+ŒBoot0010ÿUEFI: PXE IP6 Mellanox Network Adapter - 98:03:9B:85:13:B3 - 98039B8513B3 ÐA  %˜›…³ <@ÿ~ïGd-É; A¬MQÐLæPXE IP6 Mellanox Network Adapter - 98:03:9B:85:13:B3ÿBO€À³`hÕjV†:¼² VG6² ¶G–¸,Ö6ÊýS°q×pÒÝñ"2;ÚA:uIÍaßä‹Ê“Òª à˜+ŒBoot0011ÿUEFI: PXE IP6 Mellanox Network Adapter - 98:03:9B:84:B3:AE - 98039B84B3AE ÐA  %˜›„³® <@ÿ~ïGd-É; A¬MQÐLæPXE IP6 Mellanox Network Adapter - 98:03:9B:84:B3:AEÿBO€üP‹†õ¶dñ–Ðà§œšÐJ ðÚ]”ÍZKÖt0}—UžÙ)š=«ýݵ—ÔÉo‹Íaßä‹Ê“Òª à˜+ŒBoot0012ÿUEFI: PXE IP6 Mellanox Network Adapter - 98:03:9B:84:B3:AF - 98039B84B3AF ÐA  %˜›„³¯ <@ÿ~ïGd-É; A¬MQÐLæPXE IP6 Mellanox Network Adapter - 98:03:9B:84:B3:AFÿBOà€‹Xf…L ‚Ùg¡Ùñ£’ A'’ MJŽ,t;½ÀêòÛµÕu¯ë6õØßÏ`šàCž.éH˲×:=–E£¼ÚÐgeo$db½šúwY2M½`(ôçxK0‚0‚ø  aÓÄ0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110627212245Z 260627213245Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U"Microsoft Corporation UEFI CA 20110‚"0  *†H†÷ ‚0‚ ‚¥lLÇE jK ¤À‡u CTdàí’} ²s¿ ÆJEa Å-–Óõ+ ûMI›A€<¹Týæ¼ÑĤŠAŠ\Yƒh2»ŒGÉîq¼!OšŠ|ÿD?2²&H®uµîÉLJ~䂚xwM °½öÓÓ¼ú+¥Q8]õûºÛxÛÿì –Õƒ¸é¶À{@{á('ÉúïV^æ~”~ÀðD²y9åÚ²b‹M¿8pâh$É3¤7ÕXi^Ó|íÁSçN°*‡caocYê²+y× agŠ[ý^­‡º†gOqX"""΋ïTqÎP5Xv•îj±¢Õ£‚v0‚r0 +‚70# +‚7øÁk·wSJó%7N¡&{ p€0U­¿C ½‚pœŒÕO1nÕ"˜ŠÔ0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚5Bÿ0ÌÎ÷v ­hX5)F2v'|ïA'BJªm8HYUóéX4¦ ‚ª]­‚Ú€ƒA´ò¹ó]ñPù³U„B( ½²®QÅÀ¬—•!Ûüwž•s‘ˆÊ½½R¹P ßWž aí åm%Ù@@ÈΣJÂM¯šT½Ç¼¹+=I+2üj!iO›È~B4ü6‹ @À³š%u'ÍÉ£ö]Ñç6Tz¹PµÓÑ¿»tßÜ€Õíô/k/ÞfŒ°#åÇ„ØíêÁ3‚­VK-ñh•ÍÏðrð®»Ý†…˜,!L3+ðJðh‡µ’U2u¡j‚j<£%¤í­×®ËØ@Y „Ñ•Lb‘"tŒ=GD¦ä°›45±ú¶S¨,ì¤qȸºèDfäGTŽV³Ÿ˜²†Ðh>#µ/^P…Æ‚_A¡ô. à™Òluä¶iµ!†úÑöâMÑÚ­,wS%27ÇlRr•†°ñ5ajõ²;PV¦2-þ¢‰ùB†'U¡‚ÊZ›ø0˜T¦G–%/È&äA”\?å–ã…[<>?»GrUâ%"±Ù{ç*£÷Fà Ö‰ã5'bq¦ïÐ'  Y7`ø8”¸àxpøºL†‡”öà®Eîe¶£~iu’›õ¦¼YƒX€Ðæù9ñ0Jƒ—_4ÿg¥s®+>å L•W± >!f>-#ãÁ®œäµÞ X¢—3#6¢Ø|ðb ^\ ÐA  % Äzÿ` ÿ€U¿÷Ùÿ”ä²½6‰ïÜŠâ`g ªûZŸCfŠ]΢ѯ }•5Ä\|Ö<ÉÓ‹vå6c)°À¯à€]¶zD±òç(˜'Rfîlµß pðÜ ý“@>.ÒçgÛ+ºçó¢â<«FëcIÒfP«]`FàC«¶=ØÝ‹#8Shim0‚40‚  ¹A$ ,’g0  *†H†÷  0„1 0 UGB10U Isle of Man10U Douglas10U Canonical Ltd.1402U +Canonical Ltd. Master Certificate Authority0 120412111251Z 420411111251Z0„1 0 UGB10U Isle of Man10U Douglas10U Canonical Ltd.1402U +Canonical Ltd. Master Certificate Authority0‚"0  *†H†÷ ‚0‚ ‚¿[:tî!]®aíV¬½ÞÞróÝ~-Lb¬ÀmHÏ‹ûa'ÌnÙU=9Të@;±»â…4yÊ÷{¿ºzÈ-}­YϦÔéNÚ®RêLžÎÆ™ Ngex]ùÑÕ8JJz“œ£…ÛÎú‹÷¢!-›TA5Wl¼)PJ~ꙩh§;Ç2ž ‡y»h™-~“RåöëÉ›ù+í¸hI¼Ù•P@[Ųqªë\WÞqù@ Ý[¬„-PRÖáókndO[´ë äaÚZðêäB×Äþ!Ù¹ÀT•BRrIdzÈl$ñp M¥ 2Ñ W¨M㯥Ž>C¡£¦0£0U­‘™ Â*±õŒ#¶eZ&Ž4Zc0U#0€­‘™ Â*±õŒ#¶eZ&Ž4Zc0Uÿ0ÿ0 U†0CU<0:08 6 4†2http://www.canonical.com/secure-boot-master-ca.crl0  *†H†÷  ‚?}öv¥³ƒ´+zÐmRƒÄ§PœG’ÌÀ”w‚Ò®W³™õ2:ÆUÛ©VúØÔv ëäÃQÛš\œ’?sÚ”j¡™8Œ¤ˆmÁü9qÐtv>V#5ÕUG[AÂÓLÜÿ® ’œb œsà^±ý¼Öµz~Í>~fÛ[¨É9HQÿSáœ1S‘;uºæ€”pLF·”°=ÍŽàhûùG}¢ÆQÄšÌíÝÏ£]í’»¾Ñýæì3Qs¾©ô™ÛÎ fÄm½¸'wÁB”½üj ¼¯ Ý-‘ëà™Mׯeð¿r=ì\~ ˆõH5œ1»F”ñÌß«d )¶°ão°ðÛÕ6ö¦}ƒ?grub_cmd: [ -e (tftp,192.168.0.141)/grub/x86_64-efi/grub.cfg ] ãùí\œ1Y{x¬øyRÈ^2¹!@ dF‹`ç4¨ž¸€ùö.—Û,[Ïðñzb—Öƒé4grub_cmd: source (tftp,192.168.0.141)/grub/grub.cfg ’aA³#ßT Ðj­dÿŸ8ì8 KÝ1ÎW˜DA¡&µ÷I”H-zØ’›~.ÖÀ7îÊÌ×#(tftp,192.168.0.141)/grub/grub.cfg š@Æv™b,ðã­Ò¸;¾ùm¥ `AVˆáÉ‹f·E:‰RPjò’ >M6Hû¦ç!][?grub_cmd: configfile /boot/grub2/grub.cfg-01-0c:c4:7a:ff:60:1c «ÉÒBì;—'}ŒÏñÖ@½XÁê ¾ûñׯ=¤'œ¯¹õOòL³ð)Ç@Ð=PTŸ$$I*/boot/grub2/grub.cfg-01-0c:c4:7a:ff:60:1c s,q:oL:8Žá´f$·Ãþ4ÕP q¥³²Æ/@ú»tZ–IáÓBI¹pe$É $€Â˜¾°grub_cmd: set timeout=5 |‡Ð‚­Ú†ãæ| 7#¤>Je! BŽÑbÿùë&è_/6åšúB4d6*«\Ôäp§7grub_cmd: set default=xCAT OS Deployment, ugly GA hack óTˆ` »­rÚkUÜêÂøµÕ ªqÈ×ʆm²4Ϧ䎤–×".­ïÝ&ש½¸aÒgrub_cmd: menuentry xCAT OS Deployment, ugly GA hack { echo "Loading VEHV kernel ..." linux /xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/kernel imgurl=http://192.168.0.141//install/netboot/ubuntu18.04/x86_64/vgen/rootimg.tar.gz XCAT=192.168.0.141:3001 console=tty0 console=ttyS0,115200 biosdevname=0 net.ifnames=0 BOOTIF=01-$net_default_mac echo "Loading VEHV ramdisk ..." initrd /xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/initrd-stateless.gz } ¬]Ì}݆™—'õ ëÅvãÙFôì x¥Ëöìºu¢1LN/ž?Õ„êŠÜ8vºÎfy >Ž5grub_cmd: setparams xCAT OS Deployment, ugly GA hack 0è–'èŸdÝ‹Hÿæ`K~Ëó ½çD.9Ù~®¾«˜}h±Wö{j´rAeâÕ-¶ú'grub_cmd: echo Loading VEHV kernel ... }°­“šFC¼+Ѻ3M­J¸•Šð 9±PrÿÄÜsz§qx@öSG„¦ÞGk»±á(03ã grub_cmd: linux /xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/kernel imgurl=http://192.168.0.141//install/netboot/ubuntu18.04/x86_64/vgen/rootimg.tar.gz XCAT=192.168.0.141:3001 console=tty0 console=ttyS0,115200 biosdevname=0 net.ifnames=0 BOOTIF=01-0c:c4:7a:ff:60:1c Rúv…$9Â×8[Œñ‘˜òß ]ŠD÷§…¢ËŒß¢ÒšiRæG9²Cn£8qÒ¯jfäž5/xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/kernel€¤©âW)r]˜–ýñ½.ÒçgÛ+ºçó¢â<«FëcIÒfP«]`FàC«¶=ØÝ‹#8Shim0‚40‚  ¹A$ ,’g0  *†H†÷  0„1 0 UGB10U Isle of Man10U Douglas10U Canonical Ltd.1402U +Canonical Ltd. Master Certificate Authority0 120412111251Z 420411111251Z0„1 0 UGB10U Isle of Man10U Douglas10U Canonical Ltd.1402U +Canonical Ltd. Master Certificate Authority0‚"0  *†H†÷ ‚0‚ ‚¿[:tî!]®aíV¬½ÞÞróÝ~-Lb¬ÀmHÏ‹ûa'ÌnÙU=9Të@;±»â…4yÊ÷{¿ºzÈ-}­YϦÔéNÚ®RêLžÎÆ™ Ngex]ùÑÕ8JJz“œ£…ÛÎú‹÷¢!-›TA5Wl¼)PJ~ꙩh§;Ç2ž ‡y»h™-~“RåöëÉ›ù+í¸hI¼Ù•P@[Ųqªë\WÞqù@ Ý[¬„-PRÖáókndO[´ë äaÚZðêäB×Äþ!Ù¹ÀT•BRrIdzÈl$ñp M¥ 2Ñ W¨M㯥Ž>C¡£¦0£0U­‘™ Â*±õŒ#¶eZ&Ž4Zc0U#0€­‘™ Â*±õŒ#¶eZ&Ž4Zc0Uÿ0ÿ0 U†0CU<0:08 6 4†2http://www.canonical.com/secure-boot-master-ca.crl0  *†H†÷  ‚?}öv¥³ƒ´+zÐmRƒÄ§PœG’ÌÀ”w‚Ò®W³™õ2:ÆUÛ©VúØÔv ëäÃQÛš\œ’?sÚ”j¡™8Œ¤ˆmÁü9qÐtv>V#5ÕUG[AÂÓLÜÿ® ’œb œsà^±ý¼Öµz~Í>~fÛ[¨É9HQÿSáœ1S‘;uºæ€”pLF·”°=ÍŽàhûùG}¢ÆQÄšÌíÝÏ£]í’»¾Ñýæì3Qs¾©ô™ÛÎ fÄm½¸'wÁB”½üj ¼¯ ¸N¡-„qÑwr‡·‘Ðêõ¾3^ *MËŠ"Î\é}gO¸o~”£øÇ&Hí¶ÈqÈÆuëtK kernel_cmdline: /xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/kernel imgurl=http://192.168.0.141//install/netboot/ubuntu18.04/x86_64/vgen/rootimg.tar.gz XCAT=192.168.0.141:3001 console=tty0 console=ttyS0,115200 biosdevname=0 net.ifnames=0 BOOTIF=01-0c:c4:7a:ff:60:1c :Kº¦ÐNÕ*:».cW…›ì »gàI•jº+ÚÂOà„ØGÏmôШ<‚|÷°×¦Ä?(grub_cmd: echo Loading VEHV ramdisk ... Ôþ{x73( I;:ºH‘p”Kœ BHñlÐÏF&óÏ´§„ŠÇ¡õáß-6ÌY»ZSgrub_cmd: initrd /xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/initrd-stateless.gz (:¬€™5Z€?u/½ÑtSÛ ,â¸I7‰?zn©$FÑÊ ï(!†IáBrÉëB/xcat/osimage/ubuntu18.04-x86_64-netboot-vgen/initrd-stateless.gztpm2-tools-5.2/test/integration/fixtures/event-uefi-sha1-log.bin000066400000000000000000000232161412464516500247410ustar00rootroot00000000000000Ä/í­&‚ËùxAÃDç®3 ûkT U@¤­Nô¿¸:€/ *?U9‹ Ž Bh‰´Ë[#4aßä‹Ê“Òª à˜+Œ SecureBoot€›‡0n»øç•ç¾wV6f»ôQn$aßä‹Ê“Òª à˜+ŒPK€ð/¼sƒí|‰~ 2ö8â‚l>aßä‹Ê“Òª à˜+ŒKEK¡YÀ¥ä”§J‡µ«\+ðrü½šúwY2M½`(ôçxK0‚è0‚Р a ш0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110624204129Z 260624205129Z0€1 0 UUS10U Washington10URedmond10U Microsoft Corporation1*0(U!Microsoft Corporation KEK CA 20110‚"0  *†H†÷ ‚0‚ ‚Ä赊¿­W&°&ÃêçûWzD] ÚJåt*æ°ìmëì¹ãZc2|Oã §8“ŽÆõà„±š›,çõ·‘Ö áâÀ¨¬0ßHóPšd§QÈ…O †Îþ/áŸÿ‚ÀíéÍÎôSjb: C¹â%ýþùÔÄ«â#‰p·¤Mì®åœúÂ×ÁËÔèÄ/å™î$‹ìò‹êÃJûC ~µG’lÜæ‰ëõ3ë*qåùƒ<ÿ% /hvFÿºO¾Ü­q*XªûÒy=ä›e;Ì)*ŸürY¢ë®’ïö5€Æìä_ÌvÍïc’Á¯y@„y‡ãR¨è{i£‚O0‚K0 +‚70UbüCÍ >¤ËgÒ[ÙU¬{̶Š_0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚Ô„ˆõ”Ê*<û*’ × ÑñèRf¨î¢µuzª-¤vZêy·¹7jQ{döádòg¾÷¨x½ºÎˆXd ÖWÈ£_ÖÛÆÐiÎHK2·ë]Ò0õÀõ¸ºx£+þ›Û4V„ì‚Ê®A%pœkéþ×–å甲* Kÿ(){÷×|¥Ñv¹Èyí’œÂþßo~l{ÔÁEÝ4Q–9å^VØ–ô¦B³ wýòqVÌŸ†#¤‡Ë¦ýX~Ôig‘~òå ‹Š<‡„ëãνCå­-„“Žj+Z|DúRªÈ-»àRßøš=Á`°á3µ£ˆÑe ç¬|¤Á‚‡N8±/ Ňoý.¼9¶çæÃàäÍ'„ï”Bï)‹FA;gØùCYeË ¼ý’Oôu;§©$üPA@yà-O j'vnRí–i{¯÷‡ÐE­Sû0ª76aÚJi4ØhíÖÏl” ÓÏl"y­±ð¼¢F`©ÄÂ!‚ñýòèy2`¿Ø¬¥"KÊÁØKë}?W5²æOu´°`"S®‘yÖ›A†Tp²Þ 5|°4rº—`;ðy뢲]¢¸‡Åéöµ—%o8Ÿã‘úŠy˜Ãi·£ —øÊ®×ÄóÀuk4 µ™`ó\°ÅWN6Ò2„¿ž€¢3­¼cãýÅ÷6“£ÌJ'8?k ˲×:=–E£¼ÚÐgeoG db¡YÀ¥ä”§J‡µ«\+ðr뽚úwY2M½`(ôçxK0‚×0‚¿  avV0  *†H†÷  0ˆ1 0 UUS10U Washington10URedmond10U Microsoft Corporation1200U)Microsoft Root Certificate Authority 20100 111019184142Z 261019185142Z0„1 0 UUS10U Washington10URedmond10U Microsoft Corporation1.0,U%Microsoft Windows Production PCA 20110‚"0  *†H†÷ ‚0‚ ‚Ý »¢ä. ãçÅ÷–i¼!½i33ï­ËT€îƒ»Å „Ù÷Ò‹ó8°«¤­-|byÿãJ?5 pãÄçkàœÀ6uéŠ1ÝpåÜ7µtF–([‡`#,¿ÜG¥g÷Q'žrë¦É¹;S5|åÓì'¹‡þ¹É# o¨F‘Án–http://www.microsoft.com/pki/certs/MicRooCerAut_2010-06-23.crt0  *†H†÷  ‚ü|qQ¥yÂn²ï9>¼«\`ìß¨Ó éôö–…¶QˆfG¢°=*hw»‘Lb{¶ÁǺz‡4Kbz™éÊüÎJ7É-¤W|þ=ܸZúÖij…:ê³Ùnäi!7ÞÑöugÓ“W^)9Èî-áÍäEs[ÐÒÎz«‚FXÐ^³g¯l5ò¼å?$â5¢ uöV™Ôx,ÑëЈªñߺ~,c·›#!ÄùxlâX6+‘̤Ùò-ºù”@íEñΊ\k>«Óp* jà_GÑÕc 2ò¯×6*pZåBYqKWº~ƒð!<ôÁŹ“ˆE“†é± ™¾˜ËÅ•¤]bÖ c ½uw}=óE¹Ÿ—ŸËW€o3©Ïw¤bY~¡YÀ¥ä”§J‡µ«\+ðr@$½šúwY2M½`(ôçxK0‚0‚ø  aÓÄ0  *†H†÷  0‘1 0 UUS10U Washington10URedmond10U Microsoft Corporation1;09U2Microsoft Corporation Third Party Marketplace Root0 110627212245Z 260627213245Z01 0 UUS10U Washington10URedmond10U Microsoft Corporation1+0)U"Microsoft Corporation UEFI CA 20110‚"0  *†H†÷ ‚0‚ ‚¥lLÇE jK ¤À‡u CTdàí’} ²s¿ ÆJEa Å-–Óõ+ ûMI›A€<¹Týæ¼ÑĤŠAŠ\Yƒh2»ŒGÉîq¼!OšŠ|ÿD?2²&H®uµîÉLJ~䂚xwM °½öÓÓ¼ú+¥Q8]õûºÛxÛÿì –Õƒ¸é¶À{@{á('ÉúïV^æ~”~ÀðD²y9åÚ²b‹M¿8pâh$É3¤7ÕXi^Ó|íÁSçN°*‡caocYê²+y× agŠ[ý^­‡º†gOqX"""΋ïTqÎP5Xv•îj±¢Õ£‚v0‚r0 +‚70# +‚7øÁk·wSJó%7N¡&{ p€0U­¿C ½‚pœŒÕO1nÕ"˜ŠÔ0 +‚7  SubCA0 U†0Uÿ0ÿ0U#0€EfRCá~X¿ÖNž#U;:"j¨0\UU0S0Q O M†Khttp://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl0`+T0R0P+0†Dhttp://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt0  *†H†÷  ‚5Bÿ0ÌÎ÷v ­hX5)F2v'|ïA'BJªm8HYUóéX4¦ ‚ª]­‚Ú€ƒA´ò¹ó]ñPù³U„B( ½²®QÅÀ¬—•!Ûüwž•s‘ˆÊ½½R¹P ßWž aí åm%Ù@@ÈΣJÂM¯šT½Ç¼¹+=I+2üj!iO›È~B4ü6‹ @À³š%u'ÍÉ£ö]Ñç6Tz¹PµÓÑ¿»tßÜ€Õíô/k/ÞfŒ°#åÇ„ØíêÁ3‚­VK-ñh•ÍÏðrð®»Ý†…˜,!L3+ðJðh‡µ’U2u¡j‚j<£%¤í­×®ËØ@Y „Ñ•Lb‘"tŒ=GD¦ä°›45±ú¶S¨,ì¤qȸºèDfäGTŽV³Ÿ˜²†Ðh>#µ/^P…Æ‚_A¡ô. à™Òluä¶iµ!†úÑöâMÑÚ­,wS%27ÇlRr•†°ñ5ajõ²;PV¦2-þ¢‰ùB†'U¡‚ÊZ›ø0˜T¦G–%/È&äA”\?å–ã…[<>?»GrUâ%"±Ù{ç*£÷Fà Ö‰ã5'bq¦ïÐ'  Y7`ø8”¸àxpøºL†‡”öà®Eîe¶£~iu’›õ¦¼YƒX€gäŽu™T4•7íIºŽïtÛѵþ˲×:=–E£¼ÚÐgeoØdbx&ÄÁLP’@¬©Aù6“C(L0n4 œÿ³z˜œ¥Dæ»x ,x?³78v…£¯ &ÄÁLP’@¬©Aù6“C(Œ0½šúwY2M½`(ôçxK€´Ùi1¿ ý‘¦ÑO¤Ræm²@Œ¨`MA’eŸ ½šúwY2M½`(ôçxKõ/ƒ£úœûÖ’r($ÛäE4Ò[…$k;•}¬nÎz½šúwY2M½`(ôçxKÅÙØ¡†âÈ- ¯ª*o.s‡ >d÷,Nïgyj„½½šúwY2M½`(ôçxK63„ÑM. xbd„ÄY­W£ïC–&`HÐXÅ¡›¿v½šúwY2M½`(ôçxK세Kle¥ ©¾q–R0! bÖÓ h2Û²Ò à'%'ß¶=IÒ•r¦ôL½šúwY2M½`(ôçxK^ê‰T‹ `²þíÚ< Çþ›Ík”覃¸R8½šúwY2M½`(ôçxKæÆ¨Xdo±ïÆyþ(±#gþ’æ¾+6™žÿ9О½šúwY2M½`(ôçxK ß_NQìx¹mÐ%ý¶†ãŸor’xRY›eœ&½šúwY2M½`(ôçxK »C’Ú¬z¸›0¤¬eu1¹{ú«ù ¯åù¶ë ct½šúwY2M½`(ôçxK “9v-ó6«=ФcßqZ9ϰô’F\`lk×½‰Œ½šúwY2M½`(ôçxK ¾Êo)ì o3}räˆK ³H˜:* ×?O½šúwY2M½`(ôçxK Éóû™–!HÃʃ62u>Ôü ¹[1æR*Í[ü½šúwY2M½`(ôçxKo¬êÏìýN0;tô€ €˜âЀ+“oŽÇtÎ!ó†hœ½šúwY2M½`(ôçxKN: [CƦ»Ó@O4=Ï9bgΔøµ.#©Ú’ ½šúwY2M½`(ôçxK34)ÿbퟗ>HÜîå-¾.ImTµÏÖÈdÒѽšúwY2M½`(ôçxK+™Ï&B.’þ6_¿Kà 'lžáKzoÿDû/ki™9½šúwY2M½`(ôçxK+¿,§¸ñÙ'îR¶û*]ÐI¸Z+›Rœ]fb°Uø½šúwY2M½`(ôçxK,sÙ3%ºmËå‰Ô¤Æ<[“UYï’ûðPíPÄâRñ}½šúwY2M½`(ôçxK.p‘g†¦÷sQ§«pµWÆ2.©#²¨Ó¹+Q¯}½šúwY2M½`(ôçxK0f(úTw0W(ºJF}çÐ8zTõiÓvŸÎ^uì‰Ò“½šúwY2M½`(ôçxK6íºõ­A¤¡wz¿/¯^g4g^Ù^i5‚ž ªÒ½šúwY2M½`(ôçxK8AÒ!6ƒ×\ æ!`9MlN g`¶ö¹b¼…[½šúwY2M½`(ôçxK?ΛŸß>ðTR°ù^ä·ðmt:syqUŽpjÎ>s½šúwY2M½`(ôçxKC—Úʃžc|µ ’ßC¼-/²¨õŸ&üzKÔÙu’½šúwY2M½`(ôçxKGÌa'⚆à:kï,ÔøÅZmkÛ6!hÃ,ã*Zß½šúwY2M½`(ôçxKQˆ1þs‚µÐ>Æ!"‹Š¶Ty½ ¿£ÅÁÐôœ0a5½šúwY2M½`(ôçxKZéIêˆUë“ä9ÛÆ[Ú.B…,/ßg‰úg6ãÃA+\½šúwY2M½`(ôçxKk€xäAЦë{³^`’ÏGžëŒäÍçÐrÌ´/f½šúwY2M½`(ôçxKlˆTGÕYâ“Q¸&Àl¸¿ï+”­585‡rÑ“ø.ÑʽšúwY2M½`(ôçxKo(ÿqÉÛÕ¯.{¿Ë«d|ÂeÝõ²“Ͷ&õ :x^½šúwY2M½`(ôçxKqòoÒ"I~T£Fb«$—üÈ wõhéãÙ¿Ëýcu½šúwY2M½`(ôçxKrk>¶Tj0óø=›–Îöpé¨ÑpŠqæ-Ä,#Á½šúwY2M½`(ôçxKrà½gÏ]V«Šß;ݼ‚¿2¨ØªŒ^/mò”(ÖØ½šúwY2M½`(ôçxKx'¯™6,úðq}­ä±¿àCŠÑqÁZÝÂH·[øÊ¤K²Å½šúwY2M½`(ôçxK¨¹e»„Ó‡k”)©TÌ•SϪØÈ£;ý3ÿð佚úwY2M½`(ôçxK‚Û;δöCΗÃч͛YAÍ=èXo+ÚV7W_g½šúwY2M½`(ôçxK‰Z—…öÊ~ÔOÁ¡G qóñ"8bÙÿÌ:âß’=¯½šúwY2M½`(ôçxKŠÖHYñ•µõ¯ª” jag¬ÖzˆnF“dr!ÅYE¹½šúwY2M½`(ôçxK‹ô4´žÌ÷¢ÍeËì;= <5¾P_ß{Õcõ!½šúwY2M½`(ôçxKŽ¢‰Ïç «seË(îQíÓ<òPmèˆû­Ö¿€H½šúwY2M½`(ôçxK™˜ÓcÄ‘¾½tº¹M’‘soܦC£fd¼1ZB½šúwY2M½`(ôçxKžJi1ah.Uýèþõ`ëˆìþܯfÀÊ÷²·4½šúwY2M½`(ôçxK¦µ6UÓ¢¯ G'Yykä¤ T•§ØiuLHH…t§½šúwY2M½`(ôçxK§ó/PN°þ­š~ùNѺ ì]æ÷ïoð¦+“¾ß]E½šúwY2M½`(ôçxK­h&á”m&Óêóh\ˆÙ}…Þ;MË=â®Ç`ÑùÂ$Q?¼eYW×5ú)õ@νšúwY2M½`(ôçxKØËë—5õg+6~O–ÍÇIia]JélrMBÎøóú½šúwY2M½`(ôçxKé,"ë;VBÖ\ÂÊòGÒYG8„D•oYâ°Ñú½šúwY2M½`(ôçxKýÝn=)ê„Çt=­JÛǵþÁ³‘ù2@†¬ÇÖÛØ½šúwY2M½`(ôçxKþc¨Ox,ÉÓüòÌùüûÐ7`‡‡XÒb…íf›Ünm½šúwY2M½`(ôçxKþϲ2Ñ.™KmH],qgrŠ¥RY„­\¦u"š6½šúwY2M½`(ôçxKÊaJ~“”ŒÐþUÓ™ùÑ©nE AR'ÂÆ[½šúwY2M½`(ôçxKU¹› å=¼þHZ©Ç7Ï?¶ï=‘úµ™ª|«í§cµº½šúwY2M½`(ôçxKwÝ£ ˆÿ^; æb x  S^ˇæðˆŠ k/½šúwY2M½`(ôçxKÈ<±9"­™õ`tFuÝ7̔ܭZ˦G/î4qÙ9脽šúwY2M½`(ôçxK;‡S> ÃÐì¨#Ëð©AªØryÑÄ™€-Ñæ6¸©½šúwY2M½`(ôçxK“šîôõúQâ3@ÃòäHΈrRjý÷Rçó£ò¼Ÿ`I½šúwY2M½`(ôçxKdW[Ùxš.­Vö4R¯kø ùDxYuéðN-d×E½šúwY2M½`(ôçxKEÇÈ®u Ï»Hü7R}dÝdM®Ø‘<ÍŠ$ÉM…igߎiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äsiÊxçE (QsC>RÅÂR™äs€øƒ@±@dçÌN€˜¯¹F­†^ÝdEFI PART\ÀÑ&ÿZ"ÞZÇð©‡*íþG†.óÄXA€€P×W†(s*ÁøÒºK É>É;”«ãf”ÌB›ë·–›²ŠÿEFI System Partition¯=ƃ„rGŽy=iØG}äBkÍzn¶E¹ÏCmöÁ†ÿwZ€Ðæù9ñ0Jƒ—_4ÿg¥s®+>å²ÐdŸ ^’ ÐA   ÐA  *”«ãf”ÌB›ë·–›²Š4\EFI\ubuntu\shimx64.efiÿ€[SQ¬é?Ä>Æ^Àäu^žE) Ìtpm2-tools-5.2/test/integration/fixtures/event-uefiaction.bin000066400000000000000000000002751412464516500245260ustar00rootroot00000000000000-Spec ID Event03 0 @€ÍÛE1¦ìA¾'Sº&7Öå÷òV =gr´øNÔu•×*,L_ýõ»rÇPâo*®âÆV3º(Calling EFI Application from Boot Optiontpm2-tools-5.2/test/integration/fixtures/event-uefiservices.bin000066400000000000000000000003411412464516500250660ustar00rootroot00000000000000%Spec ID Event03 €…V…´ÛÔ¶}PàYEqPTÏâ±é Ý…v´ÿ4lÅl>O—ÎUů¦FùÆi¾ |ÝzÍóT`Ï}È4 ÐA &ÿÃÿtpm2-tools-5.2/test/integration/fixtures/event-uefivar.bin000066400000000000000000000003121412464516500240310ustar00rootroot00000000000000-Spec ID Event03 0 @€ÔýÑñM@AIMëÉÄSCÒ'} ÌüK³(ˆ£E¼ŠêÚºU+b}™4Œvv«1Aõ°@¤5aßä‹Ê“Òª à˜+Œ SecureBoottpm2-tools-5.2/test/integration/fixtures/event.bin000066400000000000000000000004311412464516500223740ustar00rootroot00000000000000-Spec ID Event03 0 @€Ñî~…~*åFq¾Xø?;UÄÉ)ñ fu³ÉMGðN0‘-Ù1²…2Ó'á½êС¸ñ'nÑ "Ê «¥r»ç1mµv,‘¤ÿ~X®l¦X‰ÍÄ"¢¬©`×%búö©À M¯OÃÞÇ=÷U€¤Œ|iÞ-´eµ”ÉS%0ÖëÅ?Dî.Û^4€\ÝvîCܨåUSiþ :c•ófT€Ñ°tpm2-tools-5.2/test/integration/fixtures/get-capability-tpm-prop-fixed.bin000066400000000000000000000000261412464516500270220ustar00rootroot00000000000000€ztpm2-tools-5.2/test/integration/fixtures/specid-vendordata.bin000066400000000000000000000001111412464516500246420ustar00rootroot00000000000000%Spec ID Event03 Þ­¾ïtpm2-tools-5.2/test/integration/helpers.sh000066400000000000000000000560071412464516500207200ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause set -E shopt -s expand_aliases # We get what python interpreter to run from configure, so alias python here # to make subordiante scripts work. alias python=${PYTHON:-python} # Return 0 if run by a TPM simulator, return 1 otherwise is_simulator() { # both simulators mssim and swtpm have their vendor sting set to "SW": # TPM2_PT_VENDOR_STRING_1: # raw: 0x53572020 # value: "SW" tpm2 getcap properties-fixed \ | grep -zP "TPM2_PT_VENDOR_STRING_1:\s*raw: 0x53572020" &>/dev/null } # Return 0 if algorithm is supported, return 1 otherwise # Error if TPM is simulator and algorithm is unsupported is_alg_supported() { if tpm2 testparms $1 2> /dev/null; then return 0 else if is_simulator; then echo "ERROR: $1 is not supported by the TPM simulator." exit 1 else echo "SKIP: Testing on a non-simulator TPM. Skipping unsupported algorithm $1" return 1 fi fi } # Return 0 if command is supported, return 1 otherwise # Error if TPM is simulator and command is unsupported is_cmd_supported() { if tpm2 getcap commands | grep -i "$1:" &> /dev/null; then return 0 else if is_simulator; then echo "ERROR: $1 is not supported by the TPM simulator." exit 1 else echo "SKIP: Testing on a non-simulator TPM. Skipping unsupported command $1" return 1 fi fi } function filter_algs_by() { python << pyscript from __future__ import print_function import sys import yaml with open("$1") as f: try: y = yaml.safe_load(f) for alg, details in y.items(): if $2: print(alg) except yaml.YAMLError as exc: sys.exit(exc) pyscript } populate_algs() { algs="$(mktemp)" tpm2 getcap algorithms > "${algs}" filter_algs_by "${algs}" "${1}" rm "${algs}" } populate_hash_algs() { populate_algs "details['hash'] and not details['method'] and not details['symmetric'] and not details['signing'] $1" } # Return alg argument if supported by TPM. hash_alg_supported() { local orig_alg="$1" local alg="$orig_alg" local algs_supported algs_supported="$(populate_hash_algs name)" local hex2name=( [0x04]="sha1" [0x0B]="sha256" [0x0C]="sha384" [0x0D]="sha512" [0x12]="sm3_256" ) if [ -z "$alg" ]; then echo "$algs_supported" return fi if [ "$alg" = "${alg//[^0-9a-fA-FxX]/}" ]; then alg=${hex2name["$alg"]} [ -z "$alg" ] && return fi local t_alg for t_alg in $algs_supported; do if [ "$t_alg" = "$alg" ]; then echo "$orig_alg" return fi done } # Get nice names of supported algorithms lengths # Does not work with hashes! # e.g. calling "populate_alg_lengths rsa" will print: # rsa1024 # rsa2048 populate_alg_lengths() { #set -x alg="$1" local lengths="1 128 192 224 256 384 512 1024 2048 4096" local populated="" for len in $lengths; do if tpm2 testparms "$alg$len" 2> /dev/null; then if [ -z "$populated" ]; then populated="$alg$len" else populated="$populated\n$alg$len" fi fi done; printf "$populated" } # Get nice name of the algorithm with its weakest supported key size # Does not work with hashes! # e.g. calling "weakest_alg aes" will print "aes128" weakest_alg() { populate_alg_lengths "$1" | head -n1 } # Get nice name of the algorithm with its strongest supported key size # Does not work with hashes! # e.g. calling "strongest_alg aes" will print "aes256" strongest_alg() { populate_alg_lengths "$1" | tail -n1 } # Get nice names of supported algorithm modes # Does not work with hashes! # e.g. calling "populate_alg_modes aes128" will print: # aes128cfb # aes128cbc populate_alg_modes() { #set -x alg="$1" local modes="ctr ofb cbc cfb ecb" local populated="" for mode in $modes; do if tpm2 testparms "$alg$mode" 2> /dev/null; then if [ -z "$populated" ]; then populated="$alg$mode" else populated="$populated\n$alg$mode" fi fi done; printf "$populated" } # # Verifies that the contexts of a file path provided # as the first argument loads as a YAML file. # function yaml_verify() { python << pyscript from __future__ import print_function import sys import yaml with open("$1") as f: try: y = yaml.safe_load(f) except yaml.YAMLError as exc: sys.exit(exc) pyscript } # # Given a file as argument 1, prints the value of the key # provided as argument 2 and optionally argument 3 (for nested maps). # Note that all names and values are parsed as strings. # function yaml_get_kv() { third_arg="" if [ $# -eq 3 ]; then third_arg=$3 fi python << pyscript from __future__ import print_function import sys import yaml with open("$1") as f: try: y = yaml.load(f, Loader=yaml.BaseLoader) if $# == 3: print(y["$2"]["$third_arg"]) else: print(y["$2"]) except yaml.YAMLError as exc: sys.exit(exc) pyscript } function recreate_info() { echo echo "--- To recreate this test run the following: ---" local a="export TPM2_ABRMD=\"$TPM2_ABRMD\"\n" a="$a""export TPM2_SIM=\"$TPM2_SIM\"\n" a="$a""export TPM2ABRMD_TCTI=\"$TPM2ABRMD_TCTI\"\n" a="$a""export TPM2_SIMPORT=\"$TPM2_SIMPORT\"\n" a="$a""export TPM2TOOLS_TEST_TCTI=\"$TPM2TOOLS_TEST_TCTI\"\n" a="$a""export TPM2TOOLS_TEST_PERSISTENT=\"$TPM2TOOLS_TEST_PERSISTENT\"\n" a="$a""export PATH=\"$PATH\"\n" a="$a""export srcdir=\"$srcdir\"\n" a="$a""export abs_srcdir=\"$abs_srcdir\"\n" a="$a""export abs_builddir=\"$abs_builddir\"\n" echo "#!/usr/bin/env bash" echo -e "$a" local script="$tpm2_test_original_cwd""/""$0" echo $(realpath "$script") echo "--- EOF ---" echo } tpm2_test_original_cwd="" tpm2_test_cwd="" function switch_to_test_dir() { tpm2_test_original_cwd=`pwd`; tpm2_test_cwd=$(mktemp -d ${TMPDIR:-/tmp}/tpm2_test_XXXXXX) echo "creating simulator working dir: $tpm2_test_cwd" pushd "$tpm2_test_cwd" echo "Switched to CWD: $(pwd)" } function switch_back_from_test_dir() { popd } tpm2_sim_pid="" tpm2_abrmd_pid="" tpm2_tcti_opts="" tpm2tools_tcti="" sock_tool="unknown" OS=$(uname) if [ "$OS" == "Linux" ]; then sock_tool="ss -lntp4" elif [ "$OS" == "FreeBSD" ]; then sock_tool="sockstat -l4" fi function start_sim() { local max_cnt=10 # if a user is specifying the sim port, then only attempt it once if [ -n "$TPM2_SIMPORT" ]; then max_cnt=1 fi while [ $max_cnt -gt 0 ]; do # If either the requested simulator port or the port that will be used # by mssim TCTI which is tpm2_sim_port + 1 is occupied (ESTABLISHED, TIME_WAIT, etc...), # just continue up to 10 retries # (See : https://github.com/tpm2-software/tpm2-tss/blob/master/src/tss2-tcti/tcti-mssim.c:559) if [ -z "$TPM2_SIMPORT" ]; then tpm2_sim_port="$(od -A n -N 2 -t u2 /dev/urandom | awk -v min=2321 -v max=65534 '{print ($1 % (max - min)) + min}')" else tpm2_sim_port=$TPM2_SIMPORT fi tpm2_sim_cmd_port=$((tpm2_sim_port + 1)) echo "Attempting to start simulator on port: $tpm2_sim_port" case "$TPM2_SIM" in *swtpm) "$TPM2_SIM" socket --tpm2 --server port="$tpm2_sim_port" \ --ctrl type=tcp,port="$tpm2_sim_cmd_port" \ --flags not-need-init --tpmstate dir="$PWD" &;; *tpm_server) "$TPM2_SIM" -port "$tpm2_sim_port" &;; *) echo "Unknown TPM simulator $TPM2_SIM"; return 1;; esac tpm2_sim_pid=$! sleep 1 ${sock_tool} 2>/dev/null | grep ${TPM2_SIM} | grep ${tpm2_sim_pid} | grep ${tpm2_sim_port} tpm2_sim_port_rc=$? ${sock_tool} 2>/dev/null | grep ${TPM2_SIM} | grep ${tpm2_sim_pid} | grep ${tpm2_sim_cmd_port} tpm2_sim_cmd_port_rc=$? if [[ $tpm2_sim_port_rc -eq 0 ]] && [[ $tpm2_sim_cmd_port_rc -eq 0 ]]; then echo "Started simulator on port $tpm2_sim_port in dir \"$PWD\"" TPM2_SIMPORT=$tpm2_sim_port case "$TPM2_SIM" in *swtpm) tpm2tools_tcti="swtpm:host=localhost,port=$TPM2_SIMPORT";; *tpm_server) tpm2tools_tcti="mssim:host=localhost,port=$TPM2_SIMPORT";; *) echo "Unknown TPM simulator $TPM2_SIM"; return 1;; esac echo "tpm2tools_tcti=\"$tpm2tools_tcti\"" return 0 else echo "Could not start simulator at port: $tpm2_sim_port" kill "$tpm2_sim_pid" let "max_cnt=max_cnt-1" echo "Tries left: $max_cnt" fi done echo "Maximum attempts reached. Aborting" return 1 } function start_abrmd() { local tpm2_tabrmd_opts # if we don't have an explicit TCTI to connect to, generate it if [ -z "$TPM2ABRMD_TCTI" ]; then echo "TPM2ABRMD_TCTI is empty, configuring" if [ -z "$TPM2_SIMPORT" ]; then echo "No simulator port found, can not determine ABRMD TCTI conf" return 1 fi # TCTI information for use with ABRMD local name="com.intel.tss2.Tabrmd${TPM2_SIMPORT}" tpm2_tabrmd_opts="--session --dbus-name=$name" case "$TPM2_SIM" in *swtpm) tpm2_tabrmd_opts="$tpm2_tabrmd_opts --tcti=swtpm:port=$TPM2_SIMPORT";; *tpm_server) tpm2_tabrmd_opts="$tpm2_tabrmd_opts --tcti=mssim:port=$TPM2_SIMPORT";; *) echo "Unknown TPM simulator $TPM2_SIM"; return 1;; esac echo "TPM2ABRMD_TCTI=\"$tpm2_tabrmd_opts\"" TPM2ABRMD_TCTI="$tpm2_tabrmd_opts" fi if [ $UID -eq 0 ]; then tpm2_tabrmd_opts="--allow-root $tpm2_tabrmd_opts" fi echo "tpm2-abrmd command: $TPM2_ABRMD $tpm2_tabrmd_opts $TPM2ABRMD_TCTI" $TPM2_ABRMD $tpm2_tabrmd_opts $TPM2ABRMD_TCTI & tpm2_abrmd_pid=$! sleep 2 if ! kill -0 "$tpm2_abrmd_pid"; then (>&2 echo "Could not start tpm2-abrmd \"$TPM2_ABRMD\", exit code: $?") kill -9 $tpm2_abrmd_pid return 1 fi # set a possible tools tcti to use abrmd tpm2tools_tcti="tabrmd:bus_type=session,bus_name=$name" echo "tpm2tools_tcti=\"$tpm2tools_tcti\"" return 0 } # # This start up routine performs the following actions and should # be called by testing scripts if they need a TCTI. It also outputs # information for how to recreate the test outside of the test harness. # # 1. Start the simulator if specified via env var TPM2_SIM. if TPM2_SIMPORT # is set, it attempts to start the simulator AT that port, else it tries # a random port, and sets TPM2_SIMPORT to the random port if successful. # # 2. Start abrmd if specified via env var TPM2_ABRMD. if TPM2ABRMD_TCTI is # set it starts abrmd using that TCTI, else it uses the value of TPM2_SIMPORT. # # 3. Pick a TCTI for the tools based on: # a) TPM2TOOLS_TEST_TCTI user specified, just use it. # b) TPM2TOOLS_TEST_TCTI not specified, the start_sim and start_anrmd routines # set tpm2tools_tcti variable, so use that. # function start_up() { switch_to_test_dir run_startup=true if [ -n "$TPM2_SIM" ]; then # Start the simulator echo "Starting the simulator" start_sim || exit 1 echo "Started the simulator" else echo "not starting simulator" fi if [ -n "$TPM2_ABRMD" ]; then echo "Starting tpm2-abrmd" # Start tpm2-abrmd start_abrmd || exit 1 run_startup=false else echo "not starting abrmd" fi echo "TPM2TOOLS_TEST_TCTI=$TPM2TOOLS_TEST_TCTI" if [ -z "$TPM2TOOLS_TEST_TCTI" ]; then echo "TPM2TOOLS_TEST_TCTI not set, attempting to figure out default" if [ -z "$tpm2tools_tcti" ]; then echo "The simulator not abrmd was started, cannot determine a TCTI for tools." exit 1; fi TPM2TOOLS_TEST_TCTI="$tpm2tools_tcti" fi echo "export TPM2TOOLS_TCTI=\"$TPM2TOOLS_TEST_TCTI\"" export TPM2TOOLS_TCTI="$TPM2TOOLS_TEST_TCTI" recreate_info echo "run_startup: $run_startup" if [ $run_startup = true ]; then tpm2 startup -c fi if ! tpm2 clear; then exit 1 fi } function shut_down() { echo "Shutting down" switch_back_from_test_dir fail=0 if [ -n "$tpm2_abrmd_pid" ]; then if kill -0 "$tpm2_abrmd_pid"; then if ! kill -9 "$tpm2_abrmd_pid"; then (>&2 echo "ERROR: could not kill tpm2_abrmd on pid: $tpm2_abrmd_pid") fail=1 fi else (>&2 echo "WARNING: tpm2_abrmd already stopped ($tpm2_abrmd_pid)") fi fi tpm2_abrmd_pid="" if [ -n "$tpm2_sim_pid" ]; then if kill -0 "$tpm2_sim_pid"; then if ! kill -9 "$tpm2_sim_pid"; then (>&2 echo "ERROR: could not kill tpm2 simulator on pid: $tpm2_sim_pid") fail=1 fi else (>&2 echo "WARNING: TPM simulator already stopped ($tpm2_sim_pid)") fi fi tpm2_sim_pid="" echo "Removing sim dir: $tpm2_test_cwd" rm -rf "$tpm2_test_cwd" 2>/dev/null if [ $fail -ne 0 ]; then exit 1 fi } # # Set the default EXIT handler to always shut down, tests # can override this. # trap shut_down EXIT # # Set the default on ERR handler to print the line number # and failed command. # onerror() { echo "$BASH_COMMAND on line ${BASH_LINENO[0]} failed: $?" exit 1 } trap onerror ERR # # print 0 if the list of arguments 1 to n-1 contains the last argument n # print 1 otherwise # function ina() { local n=$# local value=${!n} for ((i=1;i < $#;i++)) { if [ "${!i}" == "${value}" ]; then echo 0 return fi } echo 1 } # Causes a test to skip by exiting with error code 77 # See the automake manual for the exit codes: # https://www.gnu.org/software/automake/manual/html_node/Scripts_002dbased-Testsuites.html function skip_test() { exit 77 } function setup_fapi() { tempdir=`pwd`/$(mktemp -d tss2_fapi.XXXXXX) KEYSTORE_USER=keystore_user KEYSTORE_SYSTEM=keystore_system LOG_DIR=log PROFILE_NAME_ECC=P_ECCP256SHA256 PROFILE_NAME_RSA=P_RSA2048SHA256 if [ "$1" = "ECC" ]; then PROFILE_NAME=$PROFILE_NAME_ECC else PROFILE_NAME=$PROFILE_NAME_RSA fi mkdir -p $tempdir/$KEYSTORE_USER/policy $tempdir/$KEYSTORE_SYSTEM/policy \ $tempdir/$LOG_DIR cat > $tempdir/fapi_config.json < $tempdir/${PROFILE_NAME_RSA}.json < $tempdir/${PROFILE_NAME_ECC}.json < $tempdir/pol_authorize.json < $tempdir/pol_authorize_ref.json < $tempdir/pol_authorize_nv.json < $tempdir/pol_duplicate.json < $tempdir/pol_pcr16_0.json < $tempdir/pol_nv_read_write.json < $tempdir/pol_pwd_nv_read_write.json < $tempdir/pol_signed.json </dev/null; then echo "Expected \"$cmd\" to fail." exit 1 else true fi # Use only invalid fields for issuer - should fail if tpm2 certifyX509certutil -i "B=USA;Y=12345678901234567890;X=12345678901234567890;YXZ=12345678901234567890" &> /dev/null; then echo "Expected \"$cmd\" to fail." exit 1 else true fi exit "$fail" tpm2-tools-5.2/test/integration/tests/abrmd_extended-sessions.sh000066400000000000000000000100671412464516500252250ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=ecc alg_create_obj=sha256 alg_pcr_policy=sha1 pcr_ids=0,1,2,3 file_pcr_value=pcr.bin file_input_data=secret.data file_policy=policy.data file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_unseal_key_pub=opu_"$alg_create_obj" file_unseal_key_priv=opr_"$alg_create_obj" file_unseal_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj" file_unseal_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj" file_unseal_output_data=usl_"$file_unseal_key_ctx" file_session_file=session.dat secret=12345678 cleanup() { rm -f $file_input_data $file_primary_key_ctx $file_unseal_key_pub \ $file_unseal_key_priv $file_unseal_key_ctx $file_unseal_key_name \ $file_unseal_output_data $file_pcr_value \ $file_policy $file_session_file tpm2 flushcontext $file_session_file 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo $secret > $file_input_data tpm2 clear # # Test an extended policy session beyond client connections. This is ONLY # supported by abrmd since version: https://github.com/tpm2-software/tpm2-abrmd/ # releases/tag/1.2.0 However, bug: https://github.com/tpm2-software/tpm2-abrmd/ # issues/285 applies. # # The test works by: # Step 1: Creating a trial session and updating it with a policyPCR event to # generate a policy hash. # # Step 2: Creating an object and using that policy hash as the policy to satisfy # for usage. # # Step 3: Creating an actual policy session and using pcrpolicy event to update # the policy. # # Step 4: Using that actual policy session from step 3 in tpm2 unseal to unseal # the object. # tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 pcrread -Q -o $file_pcr_value ${alg_pcr_policy}:${pcr_ids} tpm2 startauthsession -Q -S $file_session_file tpm2 policypcr -Q -S $file_session_file -l ${alg_pcr_policy}:${pcr_ids} \ -f $file_pcr_value -L $file_policy tpm2 flushcontext $file_session_file tpm2 create -Q -g $alg_create_obj -u $file_unseal_key_pub \ -r $file_unseal_key_priv -i- -C $file_primary_key_ctx -L $file_policy \ -a 'fixedtpm|fixedparent' <<< $secret tpm2 load -Q -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx rm $file_session_file # Start a REAL encrypted and bound policy session (-a option) and perform a pcr # policy event tpm2 startauthsession --policy-session -c $file_primary_key_ctx \ -S $file_session_file tpm2 policypcr -Q -S $file_session_file -l ${alg_pcr_policy}:${pcr_ids} \ -f $file_pcr_value -L $file_policy unsealed=`tpm2 unseal -p"session:$file_session_file" -c $file_unseal_key_ctx` test "$unsealed" == "$secret" # Test resetting the policy session causes unseal to fail. tpm2 policyrestart -S $file_session_file # negative test, clear the error handler if tpm2 unseal -p"session:$file_session_file" \ -c $file_unseal_key_ctx 2>/dev/null; then echo "Expected tpm2 unseal to fail after policy reset" exit 1 else true fi # Test bounded sessions work with bind entities with auth tpm2 createprimary -Q -C o -c prim.ctx -p primepass ## Test with bounded and salted session tpm2 startauthsession -S session.ctx --hmac-session --tpmkey-context prim.ctx \ --bind-context prim.ctx --bind-auth primepass tpm2 sessionconfig session.ctx --enable-encrypt --enable-decrypt tpm2 getrandom 8 -S session.ctx tpm2 flushcontext session.ctx ## Test with bounded only session tpm2 startauthsession -S session.ctx --hmac-session \ --bind-context prim.ctx --bind-auth primepass tpm2 sessionconfig session.ctx --enable-encrypt --enable-decrypt tpm2 getrandom 8 -S session.ctx tpm2 flushcontext session.ctx ## Test with salted only session tpm2 startauthsession -S session.ctx --hmac-session \ --tpmkey-context prim.ctx tpm2 sessionconfig session.ctx --enable-encrypt --enable-decrypt tpm2 getrandom 8 -S session.ctx tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_nvundefinespecial.sh000066400000000000000000000021121412464516500252530ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 flushcontext session.ctx 2>/dev/null || true tpm2 startauthsession --policy-session -S session.ctx tpm2 policyauthvalue -S session.ctx tpm2 policycommandcode -S session.ctx TPM2_CC_NV_UndefineSpaceSpecial tpm2 nvundefine -S session.ctx 1 2>/dev/null || true tpm2 flushcontext session.ctx 2>/dev/null || true rm -f policy.dat session.ctx if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 startauthsession -S session.ctx tpm2 policyauthvalue -S session.ctx tpm2 policycommandcode -S session.ctx TPM2_CC_NV_UndefineSpaceSpecial -L policy.dat tpm2 nvdefine -C p -s 32 -a "ppread|ppwrite|authread|authwrite|platformcreate|policydelete|write_stclear|read_stclear" -L policy.dat 1 tpm2 flushcontext session.ctx tpm2 startauthsession --policy-session -S session.ctx tpm2 policyauthvalue -S session.ctx tpm2 policycommandcode -S session.ctx TPM2_CC_NV_UndefineSpaceSpecial tpm2 nvundefine -S session.ctx 1 exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyauthorize.sh000066400000000000000000000045211412464516500250110ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh pcr_ids=0 alg_pcr_policy=sha256 file_pcr_value=pcr.bin file_policy=policy.data file_authorized_policy_1=auth_policy_1.data file_authorized_policy_2=auth_policy_2.data file_session_file=session.dat file_private_key=private.pem file_public_key=public.pem file_verifying_key_public=verifying_key_public file_verifying_key_name=verifying_key_name file_verifying_key_ctx=verifying_key_ctx file_policyref=policyref cleanup() { rm -f $file_pcr_value $file_policy $file_session_file $file_private_key \ $file_public_key $file_verifying_key_public $file_verifying_key_name \ $file_verifying_key_ctx $file_policyref $file_authorized_policy_1 \ $file_authorized_policy_2 tpm2 flushcontext $file_session_file 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" generate_policy_authorize () { tpm2 startauthsession -Q -S $file_session_file tpm2 policyauthorize -Q -S $file_session_file -L $3 -i $1 -q $2 -n $4 tpm2 flushcontext $file_session_file rm $file_session_file } openssl genrsa -out $file_private_key 2048 2>/dev/null openssl rsa -in $file_private_key -out $file_public_key -pubout 2>/dev/null tpm2 loadexternal -G rsa -C n -u $file_public_key -c $file_verifying_key_ctx \ -n $file_verifying_key_name dd if=/dev/urandom of=$file_policyref bs=1 count=32 2>/dev/null tpm2 pcrread -Q -o $file_pcr_value ${alg_pcr_policy}:${pcr_ids} tpm2 startauthsession -Q -S $file_session_file tpm2 policypcr -Q -S $file_session_file -l ${alg_pcr_policy}:${pcr_ids} \ -f $file_pcr_value -L $file_policy tpm2 flushcontext $file_session_file rm $file_session_file generate_policy_authorize $file_policy $file_policyref \ $file_authorized_policy_1 $file_verifying_key_name tpm2 pcrextend \ 0:sha256=e7011b851ee967e2d24e035ae41b0ada2decb182e4f7ad8411f2bf564c56fd6f tpm2 pcrread -Q -o $file_pcr_value ${alg_pcr_policy}:${pcr_ids} tpm2 startauthsession -Q -S $file_session_file tpm2 policypcr -Q -S $file_session_file -l ${alg_pcr_policy}:${pcr_ids} \ -f $file_pcr_value -L $file_policy tpm2 flushcontext $file_session_file rm $file_session_file generate_policy_authorize $file_policy $file_policyref \ $file_authorized_policy_2 $file_verifying_key_name diff $file_authorized_policy_1 $file_authorized_policy_2 exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyauthorizenv.sh000066400000000000000000000056021412464516500253560ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh nv_test_index=0x01500001 cleanup() { tpm2 nvundefine -Q -C o $nv_test_index 2>/dev/null || true tpm2 flushcontext -t tpm2 flushcontext -l tpm2 flushcontext -s rm -f session.ctx policy.pass policyauthorizenv.1500001 prim.ctx key.pub \ key.priv key.ctx policy.pcr0 if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear # Define the test NV Index to store the auth policy tpm2 nvdefine -C o -p nvpass $nv_test_index -a "authread|authwrite" -s 34 # Define the auth policy tpm2 startauthsession -S session.ctx tpm2 policypassword -S session.ctx -L policy.pass tpm2 flushcontext session.ctx # Write the auth policy to the NV Index POLICYDIGESTALGORITHM=000b echo $POLICYDIGESTALGORITHM | xxd -p -r | cat - policy.pass | \ tpm2 nvwrite -C $nv_test_index -P nvpass $nv_test_index -i- # Define the policyauthorizenv tpm2 startauthsession -S session.ctx tpm2 policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass \ -L policyauthorizenv.1500001 $nv_test_index tpm2 flushcontext session.ctx # Create and load a sealing object with auth policy = policyauthorizenv tpm2 createprimary -C o -c prim.ctx echo "secretdata" | \ tpm2 create -C prim.ctx -u key.pub -r key.priv \ -a "fixedtpm|fixedparent|adminwithpolicy" -L policyauthorizenv.1500001 -i- tpm2 load -C prim.ctx -u key.pub -r key.priv -c key.ctx # Satisfy the auth policy stored in the NV Index and thus policyauthorizenv # And attempt user operation UNSEAL tpm2 startauthsession -S session.ctx --policy-session tpm2 policypassword -S session.ctx tpm2 policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass $nv_test_index tpm2 unseal -c key.ctx -p session:session.ctx tpm2 flushcontext session.ctx # Define another auth policy and write to the NV Index tpm2 startauthsession -S session.ctx tpm2 policypcr -S session.ctx -l sha1:23 -L policy.pcr0 tpm2 flushcontext session.ctx echo "000b" | xxd -p -r | cat - policy.pcr0 | \ tpm2 nvwrite -C $nv_test_index -P nvpass $nv_test_index -i- # Satisfy the auth policy = policypassword not stored in the NV Index and # then the policyauthorizenv and # attempt user operation UNSEAL tpm2 startauthsession -S session.ctx --policy-session tpm2 policypassword -S session.ctx # should fail trap - ERR tpm2 policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass $nv_test_index if [ $? != 1 ];then echo "FAIL:tpm2 policyauthorizenv didn't fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # Satisfy the auth policy stored in the NV Index and thus policyauthorizenv # And attempt user operation UNSEAL tpm2 startauthsession -S session.ctx --policy-session tpm2 policypcr -S session.ctx -l sha1:23 -L policy.pcr0 tpm2 policyauthorizenv -S session.ctx -C $nv_test_index -P nvpass $nv_test_index tpm2 unseal -c key.ctx -p session:session.ctx tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyauthvalue.sh000066400000000000000000000026471412464516500250040ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh policyauthvalue=policy.dat session_ctx=session.ctx o_policy_digest=policy.digest primary_key_ctx=prim.ctx key_ctx=key.ctx key_pub=key.pub key_priv=key.priv plain_txt=plain.txt signature_txt=signature.txt testpswd=testpswd cleanup() { rm -f $policyauthvalue $session_ctx $o_policy_digest $primary_key_ctx \ $key_ctx $key_pub $key_priv $plain_txt $signature_txt tpm2 flushcontext $session_ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo "plaintext" > $plain_txt tpm2 startauthsession -S $session_ctx tpm2 policyauthvalue -S $session_ctx -L $policyauthvalue tpm2 flushcontext $session_ctx rm $session_ctx tpm2 createprimary -C o -c $primary_key_ctx tpm2 create -g sha256 -G ecc -u $key_pub -r $key_priv -C $primary_key_ctx \ -L $policyauthvalue -p $testpswd tpm2 load -C $primary_key_ctx -u $key_pub -r $key_priv -c $key_ctx tpm2 sign -c $key_ctx -p $testpswd -o $signature_txt $plain_txt tpm2 verifysignature -c key.ctx -m $plain_txt -s $signature_txt tpm2 startauthsession --policy-session -S $session_ctx tpm2 policyauthvalue -S $session_ctx -L $policyauthvalue tpm2 sign -c $key_ctx -p session:$session_ctx+$testpswd -o $signature_txt $plain_txt tpm2 verifysignature -c key.ctx -m $plain_txt -s $signature_txt tpm2 flushcontext $session_ctx rm $session_ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policycommandcode.sh000066400000000000000000000036161412464516500252540ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh file_primary_key_ctx=prim.ctx file_input_data=secret.data file_policy=policy.data file_unseal_key_pub=sealkey.pub file_unseal_key_priv=sealkey.priv file_unseal_key_ctx=sealkey.ctx file_unseal_key_name=sealkey.name file_output_data=unsealed.data file_session_data=session.dat secret=12345678 cleanup() { rm -f $file_primary_key_ctx $file_input_data $file_policy \ $file_unseal_key_pub $file_unseal_key_priv $file_unseal_key_ctx \ $file_unseal_key_name $file_output_data $file_session_data if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo $secret > $file_input_data tpm2 clear tpm2 createprimary -Q -C o -c $file_primary_key_ctx tpm2 startauthsession -S $file_session_data tpm2 policycommandcode -S $file_session_data -L $file_policy TPM2_CC_Unseal tpm2 flushcontext $file_session_data rm $file_session_data echo "tpm2 create -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -L $file_policy -i- <<< $secret" tpm2 create -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -L $file_policy -i- <<< $secret tpm2 load -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx # Ensure unsealing passes with proper policy tpm2 startauthsession --policy-session -S $file_session_data tpm2 policycommandcode -S $file_session_data -L $file_policy TPM2_CC_Unseal tpm2 unseal -p session:$file_session_data -c sealkey.ctx > $file_output_data tpm2 flushcontext $file_session_data rm $file_session_data cmp -s $file_output_data $file_input_data # Test that other operations fail if tpm2 encryptdecrypt -o $file_output_data -c $file_unseal_key_ctx \ $file_input_data; then echo "tpm2 policycommandcode: Should have failed!" exit 1 else true fi exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policycountertimer.sh000066400000000000000000000041251412464516500255170ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f session.ctx prim.ctx key.pub key.priv key.ctx policy.countertimer.minute if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear # # Create a sealing object with a policy that evaluates for first minute after # TPM restart. NOTE the time is 60000 milliseconds. # tpm2 startauthsession -S session.ctx tpm2 policycountertimer -S session.ctx -L policy.countertimer.minute --ult \ 60000 tpm2 flushcontext session.ctx tpm2 createprimary -C o -c prim.ctx -Q echo "SUPERSECRET" | \ tpm2 create -Q -u key.pub -r key.priv -i- -C prim.ctx \ -L policy.countertimer.minute -a "fixedtpm|fixedparent" -c key.ctx # # ASSUMING 1 minute hasn't elapsed since clear, Try unseal in the first minute # -- Should pass # tpm2 startauthsession -S session.ctx --policy-session tpm2 policycountertimer -S session.ctx -L policy.countertimer.minute --ult \ 60000 tpm2 unseal -c key.ctx -p session:session.ctx tpm2 flushcontext session.ctx # # Test if a policycountertimer evaluates with the clock # tpm2 clear tpm2 startauthsession -S session.ctx --policy-session tpm2 policycountertimer -S session.ctx --ult clock=60000 tpm2 flushcontext session.ctx # # Test if a policycountertimer evaluates with the TPM clocks safe flag # Assuming the safe flag is set since with just started and cleared the TPM # tpm2 clear tpm2 startauthsession -S session.ctx --policy-session tpm2 policycountertimer -S session.ctx safe tpm2 flushcontext session.ctx # # Test if a policycountertimer evaluates with the TPM reset count # Assuming the value is zero since we just cleared the TPM # tpm2 clear tpm2 startauthsession -S session.ctx --policy-session tpm2 policycountertimer -S session.ctx resets=0 tpm2 flushcontext session.ctx # # Test if a policycountertimer evaluates with the TPM restart count # Assuming the value is zero since we just cleared the TPM # tpm2 clear tpm2 startauthsession -S session.ctx --policy-session tpm2 policycountertimer -S session.ctx restarts=0 tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policycphash.sh000066400000000000000000000635671412464516500242640ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f helpers.sh signing_key_private.pem signing_key_public.pem \ signing_key.ctx signing_key.name authorized.policy policy.dat \ primary.ctx key.prv key.pub key.ctx new_parent.prv new_parent.pub \ new_parent.ctx new_parent.name key.name name.hash policy.namehash \ policynamehash.signature policy.namehash verification.tkt dupprv.bin \ dupseed.dat tpm2 flushcontext session.ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" generate_policycphash() { tpm2 startauthsession -S session.ctx -g sha256 tpm2 policycphash -S session.ctx -L policy.cphash --cphash-input cp.hash tpm2 flushcontext session.ctx rm session.ctx } sign_and_verify_policycphash() { openssl dgst -sha256 -sign signing_key_private.pem \ -out policycphash.signature policy.cphash tpm2 verifysignature -c signing_key.ctx -g sha256 -m policy.cphash \ -s policycphash.signature -t verification.tkt -f rsassa } setup_authorized_policycphash() { tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt } setup_owner_policy() { tpm2 setprimarypolicy -C o -L policy.cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash } start_policy_cphash() { tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash } create_authorized_policy() { tpm2 clear # Define an authorized policy for an object openssl genrsa -out signing_key_private.pem 2048 openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout tpm2 loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx \ -n signing_key.name tpm2 startauthsession -S session.ctx -g sha256 tpm2 policyauthorize -S session.ctx -L authorized.policy -n signing_key.name tpm2 flushcontext session.ctx } # Restrict the value that can be set through tpm2 nvsetbits. create_authorized_policy tpm2 nvdefine 1 -a "policywrite|authwrite|ownerread|nt=bits" -L authorized.policy NV_INDEX_NAME=$(tpm2 nvreadpublic | grep name | awk {'print $2'}) # # Suppose TPM2_NVDefine was not run and the name was entirely created external # to the TPM. Note: This support still needs to be added. # # To emulate the absence of NV index while calculating the cpHash of NV_SetBits, # let's Undefine the NV index and define it later. # tpm2 nvundefine 1 -C o # (1) Calculate the cpHash tpm2 nvsetbits 1 -i 1 --cphash cp.hash -n $NV_INDEX_NAME --tcti=none ## Create policycphash generate_policycphash ## Sign and verify policycphash sign_and_verify_policycphash # (3) Define the NV index and write some NV index data tpm2 nvdefine 1 -a "policywrite|authwrite|ownerread|nt=bits" -L authorized.policy ## Satisfy policycphash and execute nvsetbits setup_authorized_policycphash tpm2 nvsetbits 1 -i 1 -P "session:session.ctx" tpm2 flushcontext session.ctx ## Attempt setting another bit which was not recorded in policycphash setup_authorized_policycphash trap - ERR tpm2 nvsetbits 1 -i 2 -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: nvsetbits must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvextend create_authorized_policy tpm2 nvdefine 1 -a "nt=extend|ownerread|policywrite" -L authorized.policy NV_INDEX_NAME=$(tpm2 nvreadpublic | grep name | awk {'print $2'}) # # Suppose TPM2_NVDefine was not run and the name was entirely created external # to the TPM. Note: This support still needs to be added. # # To emulate the absence of NV index while calculating the cpHash of NV_SetBits, # let's Undefine the NV index and define it later. # tpm2 nvundefine 1 -C o # (1) Calculate the cpHash echo "foo" | tpm2 nvextend -i- 1 --cphash cp.hash -n $NV_INDEX_NAME --tcti=none ## Create policycphash generate_policycphash ## Sign and verify policycphash sign_and_verify_policycphash # (3) Define the NV index tpm2 nvdefine 1 -a "nt=extend|ownerread|policywrite" -L authorized.policy ## Satisfy policycphash and execute nvsetbits setup_authorized_policycphash echo "foo" | tpm2 nvextend -i- 1 -P "session:session.ctx" tpm2 flushcontext session.ctx ## test the failing scenario setup_authorized_policycphash trap - ERR echo "food" | tpm2 nvextend -i- 1 -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: nvextend must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvincrement create_authorized_policy tpm2 nvdefine 1 -s 8 -a "nt=counter|ownerread|policywrite" -L authorized.policy tpm2 nvincrement 1 --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 nvincrement 1 -P "session:session.ctx" tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvread create_authorized_policy tpm2 nvdefine 1 -a "ownerwrite|policyread" -L authorized.policy echo "some nv data" | tpm2 nvwrite 1 -i- -C o NV_INDEX_NAME=$(tpm2 nvreadpublic | grep name | awk {'print $2'}) # # Suppose TPM2_NVDefine was not run and the name was entirely created external # to the TPM. Note: This support still needs to be added. # # To emulate the absence of NV index while calculating the cpHash of NVRead, # let's Undefine the NV index and define it later. # tpm2 nvundefine 1 -C o # (1) Calculate the cpHash tpm2 nvread 1 -s 4 --cphash cp.hash -n $NV_INDEX_NAME --tcti=none # (2) Calculate the policycphash generate_policycphash sign_and_verify_policycphash # (3) Define the NV index and write some NV index data tpm2 nvdefine 1 -a "ownerwrite|policyread" -L authorized.policy echo "some nv data" | tpm2 nvwrite 1 -i- -C o # (4) setup_authorized_policycphash tpm2 nvread 1 -s 4 -P "session:session.ctx" tpm2 flushcontext session.ctx ## test the failing scenario setup_authorized_policycphash trap - ERR tpm2 nvread 1 -s 8 --offset 1 -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: nvread must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx tpm2 nvundefine 1 -C o # Test tpm2 nvreadlock create_authorized_policy tpm2 nvdefine 1 -C o -s 32 -a "policyread|policywrite|read_stclear" \ -L authorized.policy tpm2 nvreadlock 1 -C 0x01000001 --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 nvreadlock 1 -C 0x01000001 -P "session:session.ctx" tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvwritelock create_authorized_policy tpm2 nvdefine 1 -C o -s 32 -a "policyread|policywrite|writedefine" \ -L authorized.policy tpm2 nvwritelock 1 -C 0x01000001 --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 nvwritelock 1 -C 0x01000001 -P "session:session.ctx" tpm2 flushcontext session.ctx tpm2 nvundefine 1 ## attempt with globallock attribute set tpm2 nvdefine 1 -C o -s 32 -a "ownerread|ownerwrite|globallock" tpm2 nvwritelock --global -C o --cphash cp.hash generate_policycphash setup_owner_policy tpm2 nvwritelock --global -C o -P "session:session.ctx" tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvdefine tpm2 nvdefine 1 -C o -s 32 -a "ownerread|ownerwrite" --cphash cp.hash generate_policycphash setup_owner_policy tpm2 nvdefine 1 -C o -s 32 -a "ownerread|ownerwrite" -P "session:session.ctx" tpm2 flushcontext session.ctx ## attempt failing scenario start_policy_cphash trap - ERR tpm2 nvdefine 2 -C o -s 32 -a "ownerread|ownerwrite" -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: nvdefine must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 nvundefine tpm2 nvdefine 1 tpm2 nvundefine 1 --cphash cp.hash generate_policycphash setup_owner_policy tpm2 nvundefine 1 -P "session:session.ctx" tpm2 flushcontext session.ctx ## attempt failing scenario tpm2 nvdefine 2 start_policy_cphash trap - ERR tpm2 nvundefine 2 -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: nvundefine must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx tpm2 nvundefine -C p 2 #Test tpm2 nvcertify tpm2 createprimary -C o -c primary.ctx -Q tpm2 create -G rsa -u signing_key.pub -r signing_key.priv -C primary.ctx \ -c signing_key.ctx -Q tpm2 readpublic -c signing_key.ctx -f pem -o sslpub.pem -Q tpm2 nvdefine -s 32 -C o -a "ownerread|ownerwrite|authread|authwrite" 1 dd if=/dev/urandom bs=1 count=32 status=none| tpm2 nvwrite 1 -i- tpm2 nvcertify -C signing_key.ctx -g sha256 -f plain -s rsassa \ -o signature.bin --attestation attestation.bin --size 32 1 -c o --cphash cp.hash generate_policycphash setup_owner_policy tpm2 nvcertify -C signing_key.ctx -g sha256 -f plain -s rsassa \ -o signature.bin --attestation attestation.bin --size 32 1 -c o -p "session:session.ctx" tpm2 flushcontext session.ctx tpm2 nvundefine 1 #Test tpm2 policynv tpm2 nvdefine -C o -a "ownerwrite|ownerread" -s 2 1 operandA=0x81 operandB=0x80 echo $operandA | xxd -r -p | tpm2 nvwrite -C o -i- 1 tpm2 startauthsession -S policy_session.ctx --policy-session -g sha256 echo $operandB | xxd -r -p | tpm2 policynv -i- -C o --cphash cp.hash 1 neq -S policy_session.ctx generate_policycphash setup_owner_policy echo $operandB | xxd -r -p | tpm2 policynv -S policy_session.ctx -i- -C o -P "session:session.ctx" 1 neq tpm2 flushcontext policy_session.ctx tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 policyauthorizenv tpm2 nvdefine -C o 1 -a "ownerread|ownerwrite" -s 34 tpm2 startauthsession -S session.ctx tpm2 policypassword -S session.ctx -L policy.pass tpm2 flushcontext session.ctx POLICYDIGESTALGORITHM=000b echo $POLICYDIGESTALGORITHM | xxd -p -r | cat - policy.pass | \ tpm2 nvwrite -C o 1 -i- tpm2 startauthsession -S policy_session.ctx --policy-session tpm2 policyauthorizenv -S policy_session.ctx -C o 1 --cphash cp.hash generate_policycphash setup_owner_policy tpm2 policypassword -S policy_session.ctx tpm2 policyauthorizenv -S policy_session.ctx -C o 1 -P "session:session.ctx" tpm2 flushcontext policy_session.ctx tpm2 flushcontext session.ctx tpm2 nvundefine 1 # Test tpm2 policysecret tpm2 startauthsession -S policy_session.ctx --policy-session -g sha256 tpm2 policysecret -S policy_session.ctx -c o --cphash cp.hash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policyauthvalue -S session.ctx -L policy.authval tpm2 policycphash -S session.ctx --cphash cp.hash -L policy.authval_cphash tpm2 flushcontext session.ctx tpm2 setprimarypolicy -C o -L policy.authval_cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policyauthvalue -S session.ctx tpm2 policycphash -S session.ctx --cphash cp.hash ## Changing the policysecret authhandle parameter fro "o" to "p" should fail tpm2 policysecret -S policy_session.ctx -c o session:session.ctx tpm2 flushcontext session.ctx tpm2 flushcontext policy_session.ctx # Test tpm2 create create_authorized_policy tpm2 createprimary -C o -c prim.ctx -G rsa -L authorized.policy tpm2 create -C prim.ctx -G rsa --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 create -C prim.ctx -G rsa -P "session:session.ctx" tpm2 flushcontext session.ctx ## Attempt creating a key type that was not recorded in policycphash setup_authorized_policycphash trap - ERR tpm2 create -C prim.ctx -G aes -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: tpm2 create must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # Test tpm2 load create_authorized_policy tpm2 createprimary -C o -c prim.ctx -G rsa -L authorized.policy tpm2 create -C prim.ctx -G rsa -u key.pub -r key.priv tpm2 create -C prim.ctx -G rsa -u key_2.pub -r key_2.priv tpm2 load -C prim.ctx -u key.pub -r key.priv --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 load -C prim.ctx -u key.pub -r key.priv -c key.ctx -P "session:session.ctx" tpm2 flushcontext session.ctx ## Attempt loading another key that was not recorded in policycphash setup_authorized_policycphash trap - ERR tpm2 load -C prim.ctx -u key_2.pub -r key_2.priv -c key_2.ctx \ -P "session:session.ctx" if [ $? == 0 ];then echo "ERROR: tpm2 load must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # Test tpm2 activatecredential (using legacy option --cphash) create_authorized_policy tpm2 createprimary -C o -c prim.ctx -G rsa tpm2 readpublic -c prim.ctx -o prim.pub tpm2 create -C prim.ctx -u key.pub -r key.priv -c key.ctx -L authorized.policy tpm2 readpublic -c key.ctx -n key.name echo "plaintext" > plain.txt tpm2 makecredential -u prim.pub -s plain.txt -n `xxd -p -c 34 key.name` \ -o cred.secret tpm2 activatecredential -c key.ctx -C prim.ctx -i cred.secret -o act_cred.secret \ --cphash cp.hash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policycphash -S session.ctx -L policy.cphash --cphash cp.hash tpm2 policycommandcode -S session.ctx TPM2_CC_ActivateCredential -L policy.cphash tpm2 flushcontext session.ctx sign_and_verify_policycphash tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash cp.hash tpm2 policycommandcode -S session.ctx TPM2_CC_ActivateCredential tpm2 policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt tpm2 activatecredential -c key.ctx -C prim.ctx -i cred.secret -o act_cred.secret \ -p "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 unseal create_authorized_policy tpm2 createprimary -C o -c prim.ctx echo "plaintext" | \ tpm2 create -C prim.ctx -c key.ctx -u key.pub -r key.priv -L authorized.policy -i- tpm2 unseal -c key.ctx --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 unseal -c key.ctx -p "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 changeauth tpm2 clear tpm2 changeauth -c o ownerpassword --cphash cp.hash generate_policycphash setup_owner_policy tpm2 changeauth -c o ownerpassword -p session:session.ctx tpm2 flushcontext session.ctx ## Negative test tpm2 clear tpm2 changeauth -c o ownerpassword --cphash cp.hash generate_policycphash setup_owner_policy trap - ERR tpm2 changeauth -c o wrongownerpassword -p session:session.ctx if [ $? == 0 ];then echo "ERROR: tpm2 load must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx #Test tpm2 duplicate create_authorized_policy tpm2 createprimary -C o -g sha256 -G rsa -c primary.ctx tpm2 create -C primary.ctx -g sha256 -G rsa -r duplicable_key.prv \ -u duplicable_key.pub -a "sensitivedataorigin|sign|decrypt|encryptedduplication" \ -L authorized.policy tpm2 load -C primary.ctx -r duplicable_key.prv -u duplicable_key.pub \ -c duplicable_key.ctx tpm2 create -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub -a "decrypt|fixedparent|fixedtpm|restricted|\ sensitivedataorigin" tpm2 loadexternal -C o -u new_parent.pub -c new_parent.ctx dd if=/dev/urandom of=sym_key_in.bin bs=1 count=16 status=none tpm2 duplicate -C new_parent.ctx -c duplicable_key.ctx -G aes \ -i sym_key_in.bin -r dupprv.bin -s dupseed.dat --cphash cp.hash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policycommandcode -S session.ctx -L policy.cphash TPM2_CC_Duplicate tpm2 flushcontext session.ctx sign_and_verify_policycphash tpm2 startauthsession --policy-session -S session.ctx -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policycommandcode -S session.ctx TPM2_CC_Duplicate tpm2 policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt tpm2 duplicate -C new_parent.ctx -c duplicable_key.ctx -G aes \ -i sym_key_in.bin -r dupprv.bin -s dupseed.dat -p "session:session.ctx" tpm2 flushcontext session.ctx ## attempt failing scenario dd if=/dev/urandom of=sym_key_in.bin bs=1 count=16 status=none tpm2 startauthsession --policy-session -S session.ctx -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policycommandcode -S session.ctx TPM2_CC_Duplicate tpm2 policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt trap - ERR tpm2 duplicate -C new_parent.ctx -c duplicable_key.ctx -G aes \ -i sym_key_in.bin -r dupprv.bin -s dupseed.dat -p "session:session.ctx" if [ $? == 0 ];then echo "ERROR: tpm2 duplicate must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # Test tpm2 import create_authorized_policy tpm2 createprimary -C o -g sha256 -G rsa -c primary.ctx tpm2 create -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub -c new_parent.ctx -L authorized.policy \ -a "restricted|sensitivedataorigin|decrypt|userwithauth" tpm2 startauthsession -S session.ctx tpm2 policycommandcode -S session.ctx -L dpolicy.dat TPM2_CC_Duplicate tpm2 flushcontext session.ctx tpm2 create -C primary.ctx -g sha256 -G rsa -p foo -r dupkey.prv -u dupkey.pub \ -L dpolicy.dat -a "sensitivedataorigin|decrypt|userwithauth" -c dupkey.ctx tpm2 startauthsession --policy-session -S session.ctx tpm2 policycommandcode -S session.ctx TPM2_CC_Duplicate tpm2 duplicate -C new_parent.ctx -c dupkey.ctx -G null -p "session:session.ctx" \ -r duplicated.prv -s dup.seed tpm2 flushcontext session.ctx tpm2 import -C new_parent.ctx -u dupkey.pub -i duplicated.prv -r imported_dup.prv \ -s dup.seed --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 import -C new_parent.ctx -u dupkey.pub -i duplicated.prv -r imported_dup.prv \ -s dup.seed -P "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 rsadecrypt create_authorized_policy tpm2 createprimary -C o -c prim.ctx tpm2 create -C prim.ctx -c key.ctx -u key.pub -r key.priv -L authorized.policy \ -G rsa echo "plaintext" > plain.txt tpm2 rsaencrypt -c key.ctx -o enc.out plain.txt tpm2 rsadecrypt -c key.ctx -s rsaes enc.out --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 rsadecrypt -c key.ctx -s rsaes enc.out -o dec.out -p "session:session.ctx" tpm2 flushcontext session.ctx # Attempt failing case dd if=/dev/urandom of=rand.om bs=1 count=256 status=none setup_authorized_policycphash trap - ERR tpm2 rsadecrypt -c key.ctx -s rsaes rand.om -o dec.out -p "session:session.ctx" if [ $? == 0 ];then echo "ERROR: tpm2 rsadecrypt must fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # Test tpm2 certify create_authorized_policy tpm2 createprimary -C o -G rsa -g sha256 -c prim.ctx -p primarypass tpm2 create -C prim.ctx -c key.ctx -G rsa -u key.pub -r key.priv \ -L authorized.policy -P primarypass tpm2 certify -c prim.ctx -C key.ctx -g sha256 --cphash cp.hash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policycommandcode -S session.ctx -L policy.cphash TPM2_CC_Certify tpm2 flushcontext session.ctx sign_and_verify_policycphash tpm2 startauthsession --policy-session -S session.ctx -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 policycommandcode -S session.ctx TPM2_CC_Certify tpm2 policyauthorize -S session.ctx -i policy.cphash -n signing_key.name \ -t verification.tkt tpm2 certify -c prim.ctx -C key.ctx -g sha256 -o attest.out -s sig.out \ -p "session:session.ctx" -P primarypass tpm2 flushcontext session.ctx # Test tpm2 certifycreation create_authorized_policy tpm2 createprimary -C o -c prim.ctx --creation-data create.dat \ -d create.dig -t create.ticket tpm2 create -G rsa -u rsa.pub -r rsa.priv -C prim.ctx -c signingkey.ctx \ -L authorized.policy tpm2 certifycreation -C signingkey.ctx -c prim.ctx -d create.dig \ -t create.ticket -g sha256 -f plain -s rsassa --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 certifycreation -C signingkey.ctx -c prim.ctx -d create.dig \ -t create.ticket -g sha256 -o sig.nature --attestation attestat.ion -f plain \ -s rsassa -P "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 quote create_authorized_policy tpm2 createprimary -C e -c primary.ctx tpm2 create -C primary.ctx -u key.pub -r key.priv -c key.ctx \ -L authorized.policy tpm2 quote -Q -c key.ctx -l 0x0004:16,17,18+0x000b:16,17,18 --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 quote -Q -c key.ctx -l 0x0004:16,17,18+0x000b:16,17,18 \ -p "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 gettime create_authorized_policy tpm2 createprimary -C e -c primary.ctx tpm2 create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx \ -c rsa.ctx -L authorized.policy tpm2 gettime -c rsa.ctx -q "cafebabe" --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 gettime -c rsa.ctx -q "cafebabe" -o attest.sig --attestation attest.data \ -p "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 sign create_authorized_policy tpm2 createprimary -C e -c primary.ctx tpm2 create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx -c rsa.ctx \ -L authorized.policy echo "my message" > message.dat tpm2 sign -c rsa.ctx -g sha256 message.dat --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 sign -c rsa.ctx -g sha256 message.dat -o signature.dat \ -p "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 createprimary tpm2 clear tpm2 createprimary -C o -q "cafebabe" --cphash cp.hash generate_policycphash setup_owner_policy tpm2 createprimary -C o -q "cafebabe" -P "session:session.ctx" -c prim.ctx tpm2 flushcontext session.ctx # Test tpm2 hierarchycontrol tpm2 clear tpm2 hierarchycontrol -C p shEnable clear --cphash cp.hash generate_policycphash tpm2 setprimarypolicy -C p -L policy.cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 hierarchycontrol -C p shEnable clear -P "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 setprimarypolicy tpm2 startauthsession -S session.ctx tpm2 policyauthvalue -S session.ctx -L policy.authvalue tpm2 flushcontext session.ctx create_authorized_policy tpm2 setprimarypolicy -C o -L authorized.policy -g sha256 tpm2 setprimarypolicy -C o -L policy.authvalue -g sha256 --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 setprimarypolicy -C o -L policy.authvalue -g sha256 -P "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 clear tpm2 clear tpm2 clear -c l --cphash cp.hash generate_policycphash tpm2 setprimarypolicy -C l -L policy.cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 clear -c l "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 clearcontrol tpm2 clear tpm2 clearcontrol -C l s --cphash cp.hash generate_policycphash tpm2 setprimarypolicy -C l -L policy.cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 clearcontrol -C l s -P "session:session.ctx" tpm2 flushcontext session.ctx # Test tpm2 dictionarylockout tpm2 clearcontrol -C p c tpm2 clear tpm2 dictionarylockout -s -n 5 -t 6 -l 7 --cphash cp.hash generate_policycphash tpm2 setprimarypolicy -C l -L policy.cphash -g sha256 tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policycphash -S session.ctx --cphash-input cp.hash tpm2 dictionarylockout -s -n 5 -t 6 -l 7 --cphash cp.hash -p "session:session.ctx" tpm2 flushcontext session.ctx # Test evictcontrol tpm2 clear tpm2 createprimary -C o -c prim.ctx tpm2 evictcontrol -C o -c prim.ctx 0x81010001 --cphash cp.hash generate_policycphash setup_owner_policy tpm2 evictcontrol -C o -c prim.ctx 0x81010001 -P "session:session.ctx" tpm2 flushcontext session.ctx # Test clockset tpm2 clear let clockset=`tpm2 readclock | grep clock | grep -v info | awk '{print $2}'`+100000 tpm2 setclock -c o $clockset --cphash cp.hash generate_policycphash setup_owner_policy tpm2 setclock -c o $clockset -p "session:session.ctx" tpm2 flushcontext session.ctx # Test clockrateadjust tpm2 clear tpm2 clockrateadjust s --cphash cp.hash generate_policycphash setup_owner_policy tpm2 clockrateadjust s -p "session:session.ctx" tpm2 flushcontext session.ctx # Test nvwrite create_authorized_policy tpm2 nvdefine 1 -s 8 -a "ownerread|authwrite|policywrite" -L authorized.policy echo "foo" | tpm2 nvwrite 1 -i- --cphash cp.hash xxd -p cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash echo "foo" | tpm2 nvwrite 1 -i- -P "session:session.ctx" tpm2 flushcontext session.ctx # Test encryptdecrypt create_authorized_policy tpm2 createprimary -Q -C e -g sha1 -G rsa -c primary.ctx tpm2 create -Q -g sha256 -G aes -u key.pub -r key.priv -C primary.ctx \ -c decrypt.ctx -L authorized.policy dd if=/dev/urandom of=iv.dat bs=16 count=1 echo "plaintext" > secret.dat cat secret.dat | tpm2 encryptdecrypt -c decrypt.ctx --iv iv.dat --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash echo "plaintext" | tpm2 encryptdecrypt -c decrypt.ctx --iv iv.dat:iv2.dat \ -p "session:session.ctx" > secret2.dat # Test tpm2 hmac create_authorized_policy tpm2 createprimary -Q -C o -c prim.ctx tpm2 create -Q -C prim.ctx -c key.ctx -u key.pub -r key.priv -G hmac \ -L authorized.policy echo "testdata" > plain.txt tpm2 hmac -c key.ctx plain.txt --cphash cp.hash generate_policycphash sign_and_verify_policycphash setup_authorized_policycphash tpm2 hmac -c key.ctx plain.txt -o hmac.bin -p "session:session.ctx" tpm2 flushcontext session.ctx # Test if specifying the : in the cphash path has effect on cphash alg TPM2_ALG_SHA256_SZ=34 TPM2_ALG_SHA1_SZ=22 ## Default must be sha256 expected_hash_len=$TPM2_ALG_SHA256_SZ tpm2 getrandom 8 --cphash cp.hash file_size=`ls -l cp.hash | awk {'print $5'}` test $file_size -eq $expected_hash_len ## Check if a specific hash can be enforced with : expected_hash_len=$TPM2_ALG_SHA1_SZ tpm2 getrandom 8 --cphash sha1:cp.hash file_size=`ls -l cp.hash | awk {'print $5'}` test $file_size -eq $expected_hash_len exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyduplicationselect.sh000066400000000000000000000057441412464516500265220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #;**********************************************************************; source helpers.sh source_parent_object=src_o.ctx new_parent_object=dst_n.ctx new_parent_name=dst_n.name duplicable_object_private=dupkey.priv duplicable_object_public=dupkey.pub duplicable_object=dupkey.ctx duplicable_object_name=dupkey.name policy_duplication_select=policydupselect.dat duplicated_object_private=dupkey_new.priv duplicated_object_seed=dupseed.dat policy_session=session.dat unintended_new_parent_object=dst2_n.ctx unintended_new_parent_name=dst2_n.name cleanup() { rm -f $source_parent_object $new_parent_object $new_parent_name \ $duplicable_object_private $duplicable_object_public $duplicable_object \ $policy_duplication_select $duplicated_object_private $policy_session \ $duplicated_object_seed $duplicable_object_name \ $unintended_new_parent_object $unintended_new_parent_name \ if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Error trapped and reported tpm2 clear # Create source parent and destination(or new) parent tpm2 createprimary -C n -g sha256 -G rsa -c $new_parent_object -Q tpm2 createprimary -C o -g sha256 -G rsa -c $source_parent_object -Q # Create the restricted parent policy tpm2 readpublic -c $new_parent_object -n $new_parent_name -Q tpm2 startauthsession -S $policy_session tpm2 policyduplicationselect -S $policy_session -N $new_parent_name \ -L $policy_duplication_select -Q tpm2 flushcontext $policy_session rm $policy_session # Create the object to be duplicated using the policy tpm2 create -C $source_parent_object -g sha256 -G rsa \ -r $duplicable_object_private -u $duplicable_object_public \ -L $policy_duplication_select -a "sensitivedataorigin|sign|decrypt" \ -c $duplicable_object -Q # Satisfy the policy and duplicate the object tpm2 readpublic -c $duplicable_object -n $duplicable_object_name -Q tpm2 startauthsession -S $policy_session --policy-session tpm2 policyduplicationselect -S $policy_session -N $new_parent_name \ -n $duplicable_object_name -Q tpm2 duplicate -C $new_parent_object -c $duplicable_object -G null \ -p session:$policy_session -r $duplicated_object_private \ -s $duplicated_object_seed tpm2 flushcontext $policy_session rm $policy_session # Attempt duplication to unintended parent tpm2 createprimary -C n -g sha256 -G rsa -c $unintended_new_parent_object -Q tpm2 readpublic -c $new_parent_object -n $unintended_new_parent_name -Q tpm2 startauthsession -S $policy_session --policy-session tpm2 policyduplicationselect -S $policy_session -N $unintended_new_parent_name \ -n $duplicable_object_name -Q ## Disable error reporting for expected failures to follow trap - ERR tpm2 duplicate -C $unintended_new_parent_object -c $duplicable_object -G null \ -p session:$policy_session -r $duplicated_object_private \ -s $duplicated_object_seed ## Restore error reporting trap onerror ERR tpm2 flushcontext $policy_session rm $policy_session exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policynamehash.sh000066400000000000000000000074621412464516500245720ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f helpers.sh signing_key_private.pem signing_key_public.pem \ signing_key.ctx signing_key.name authorized.policy policy.dat \ primary.ctx key.prv key.pub key.ctx new_parent.prv new_parent.pub \ new_parent.ctx new_parent.name key.name name.hash policy.namehash \ policynamehash.signature policy.namehash verification.tkt dupprv.bin \ dupseed.dat tpm2 flushcontext session.ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" # # Restrict key duplication to specific new parent and specific duplicable key. # # Generate a duplicable object openssl genrsa -out signing_key_private.pem 2048 openssl rsa -in signing_key_private.pem -out signing_key_public.pem -pubout tpm2 loadexternal -G rsa -C o -u signing_key_public.pem -c signing_key.ctx \ -n signing_key.name tpm2 startauthsession -S session.ctx -g sha256 tpm2 policyauthorize -S session.ctx -L authorized.policy -n signing_key.name tpm2 policycommandcode -S session.ctx -L policy.dat TPM2_CC_Duplicate tpm2 flushcontext session.ctx tpm2 createprimary -C o -g sha256 -G rsa -c primary.ctx -Q ## The duplicable key tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r key.prv -u key.pub \ -L policy.dat -a "sensitivedataorigin|sign|decrypt" tpm2 load -Q -C primary.ctx -r key.prv -u key.pub -c key.ctx # Create the new parent tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub \ -a "decrypt|fixedparent|fixedtpm|restricted|sensitivedataorigin" tpm2 loadexternal -Q -C o -u new_parent.pub -c new_parent.ctx # Modify the duplicable key policy to namehash policy to restrict parent and key tpm2 readpublic -Q -c new_parent.ctx -n new_parent.name tpm2 readpublic -Q -c key.ctx -n key.name cat key.name new_parent.name | openssl dgst -sha256 -binary > name.hash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policynamehash -L policy.namehash -S session.ctx -n name.hash tpm2 flushcontext session.ctx openssl dgst -sha256 -sign signing_key_private.pem \ -out policynamehash.signature policy.namehash tpm2 startauthsession -S session.ctx -g sha256 tpm2 policyauthorize -S session.ctx -L authorized.policy -i policy.namehash \ -n signing_key.name tpm2 policycommandcode -S session.ctx -L policy.dat TPM2_CC_Duplicate tpm2 flushcontext session.ctx # Satisfy the policy and attempt key duplication tpm2 verifysignature -c signing_key.ctx -g sha256 -m policy.namehash \ -s policynamehash.signature -t verification.tkt -f rsassa tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policynamehash -S session.ctx -n name.hash tpm2 policyauthorize -S session.ctx -i policy.namehash -n signing_key.name \ -t verification.tkt tpm2 policycommandcode -S session.ctx TPM2_CC_Duplicate tpm2 duplicate -C new_parent.ctx -c key.ctx -G null -p "session:session.ctx" \ -r dupprv.bin -s dupseed.dat tpm2 flushcontext session.ctx # Attempt duplicating the key to a parent that is not in the policynamehash tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r unintended_parent.prv \ -u unintended_parent.pub \ -a "decrypt|fixedparent|fixedtpm|restricted|sensitivedataorigin" tpm2 loadexternal -Q -C o -u unintended_parent.pub -c unintended_parent.ctx tpm2 startauthsession -S session.ctx --policy-session -g sha256 tpm2 policynamehash -S session.ctx -n name.hash tpm2 policyauthorize -S session.ctx -i policy.namehash -n signing_key.name \ -t verification.tkt tpm2 policycommandcode -S session.ctx TPM2_CC_Duplicate trap - ERR tpm2 duplicate -C unintended_parent.ctx -c key.ctx -G null \ -p "session:session.ctx" -r dupprv.bin -s dupseed.dat if [ $? == 0 ];then echo "ERROR: Duplication had to fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policynv.sh000066400000000000000000000051341412464516500234230ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh nv_test_index=0x01500001 cleanup() { tpm2 nvundefine -Q -C o $nv_test_index 2>/dev/null || true tpm2 flushcontext -t tpm2 flushcontext -l tpm2 flushcontext -s rm -f session.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } # Data written to NV index --> 129 or -127 operandA=0x81 # Data specified in command line options for comparison operandB=0 evaluate_failing_test_case() { tpm2 startauthsession -S session.ctx --policy-session trap - ERR echo $operandA | xxd -r -p | \ tpm2 policynv -S session.ctx -i- -P nvpass $nv_test_index eq if [ $? != 1 ];then echo "FAIL: Expected tpm2 policynv to fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx } evaluate_passing_test_case() { tpm2 startauthsession -S session.ctx --policy-session echo $operandB | xxd -r -p | \ tpm2 policynv -S session.ctx -i- -P nvpass $nv_test_index $1 tpm2 flushcontext session.ctx } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear # Perform any comparison operation on an undefined NV index --> Should fail evaluate_failing_test_case # Define an NV index tpm2 nvdefine -C o -p nvpass $nv_test_index -a "authread|authwrite" -s 2 # Perform any comparison operation on an unwritten NV index --> Should fail evaluate_failing_test_case # Write data to NV index --> This is operandA echo $operandA | xxd -r -p | tpm2 nvwrite -P nvpass -i- $nv_test_index # Perform comparison operation "eq" operandB=0x81 evaluate_passing_test_case eq # Perform comparison operation "neq" operandB=0x80 evaluate_passing_test_case neq # Perform comparison operation "sgt" operandB=0x82 evaluate_passing_test_case sgt # Perform comparison operation "ugt" operandB=0x80 evaluate_passing_test_case ugt # Perform comparison operation "slt" operandB=0x80 evaluate_passing_test_case slt # Perform comparison operation "ult" operandB=0x82 evaluate_passing_test_case ult # Perform comparison operation "sge" operandB=0x82 evaluate_passing_test_case sge operandB=0x81 evaluate_passing_test_case sge # Perform comparison operation "uge" operandB=0x80 evaluate_passing_test_case uge operandB=0x81 evaluate_passing_test_case uge # Perform comparison operation "sle" operandB=0x80 evaluate_passing_test_case sle operandB=0x81 evaluate_passing_test_case sle # Perform comparison operation "ule" operandB=0x82 evaluate_passing_test_case ule operandB=0x81 evaluate_passing_test_case ule # Perform comparison operation "bs" operandB=0x81 evaluate_passing_test_case bs # Perform comparison operation "bc" operandB=0x7E evaluate_passing_test_case bc exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policynvwritten.sh000066400000000000000000000026651412464516500250460ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh POLICYSESSION=1 session_file=session.dat cleanup() { rm -f $session_file nvwrite.policy if [ "${1}" != "no-shutdown" ]; then shut_down fi } setup_nv_written_policy() { if [ $1 == $POLICYSESSION ];then tpm2 startauthsession -S $session_file --policy-session else tpm2 startauthsession -S $session_file fi tpm2 policycommandcode -S $session_file TPM2_CC_NV_Write tpm2 policynvwritten -S $session_file -L nvwrite.policy c } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 clear # Create a write once NV index. To do this the NV index is defined with a write # policy that is valid only if the NV index attribute "TPMA_NV_WRITTEN" was # never set. #Define the NV index write policy setup_nv_written_policy tpm2 flushcontext $session_file # Define the NV index with the policy tpm2 nvdefine -s 1 -a "authread|policywrite" -p nvrdpass -L nvwrite.policy # Write the NV index by satisfying the policy setup_nv_written_policy $POLICYSESSION echo 0xAA | xxd -r -p | tpm2 nvwrite 0x01000000 -i- -P session:$session_file tpm2 flushcontext $session_file # Attempt writing the NV index again setup_nv_written_policy $POLICYSESSION trap - ERR echo 0xAA | xxd -r -p | tpm2 nvwrite 0x01000000 -i- -P session:$session_file if [ $? != 1 ];then echo "FAIL: Expected tpm2 policynvwritten to fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.dat exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyor.sh000066400000000000000000000052261412464516500234220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh policy_1=policy.1 policy_2=policy.2 policy_init=policy.init test_vector=test.vector policyor_cc=policyor.cc session_ctx=session.ctx o_policy_digest=policy.digest concatenated=con.cat cleanup() { rm -f $policy_1 $policy_2 $policy_init $test_vector $policyor_cc \ $session_ctx $policy_digest $concatenated \ set1.pcr0.policy set2.pcr0.policy prim.ctx sealkey.priv sealkey.pub \ sealkey.ctx policyOR tpm2 flushcontext $session_ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" dd if=/dev/urandom of=$policy_1 bs=1 count=32 dd if=/dev/urandom of=$policy_2 bs=1 count=32 dd if=/dev/zero of=$policy_init bs=1 count=32 echo "00000171" | xxd -r -p > $policyor_cc cat $policy_init $policyor_cc $policy_1 $policy_2 > $concatenated openssl dgst -binary -sha256 $concatenated > $test_vector tpm2 startauthsession -S $session_ctx tpm2 policyor -L $o_policy_digest -S $session_ctx sha256:$policy_1,$policy_2 tpm2 flushcontext $session_ctx diff $test_vector $o_policy_digest # Test case to compound two PCR policies tpm2 pcrreset 23 tpm2 startauthsession -S session.ctx tpm2 policypcr -S session.ctx -l sha1:23 -L set1.pcr0.policy tpm2 flushcontext session.ctx rm session.ctx tpm2 pcrextend 23:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 tpm2 startauthsession -S session.ctx tpm2 policypcr -S session.ctx -l sha1:23 -L set2.pcr0.policy tpm2 flushcontext session.ctx rm session.ctx tpm2 startauthsession -S session.ctx tpm2 policyor -S session.ctx -L policyOR \ sha256:set1.pcr0.policy,set2.pcr0.policy tpm2 flushcontext session.ctx rm session.ctx tpm2 createprimary -C o -c prim.ctx tpm2 create -g sha256 -u sealkey.pub -r sealkey.priv -L policyOR -C prim.ctx \ -i- <<< "secretpass" tpm2 load -C prim.ctx -c sealkey.ctx -u sealkey.pub -r sealkey.priv tpm2 startauthsession -S session.ctx --policy-session tpm2 policypcr -S session.ctx -l sha1:23 tpm2 policyor -S session.ctx -L policyOR \ sha256:set1.pcr0.policy,set2.pcr0.policy unsealed=`tpm2 unseal -p session:session.ctx -c sealkey.ctx` echo $unsealed tpm2 flushcontext session.ctx rm session.ctx tpm2 pcrextend 23:sha1=f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 tpm2 startauthsession -S session.ctx --policy-session tpm2 policypcr -S session.ctx -l sha1:23 tpm2 pcrreset 23 tpm2 startauthsession -S session.ctx --policy-session tpm2 policypcr -S session.ctx -l sha1:23 tpm2 policyor -S session.ctx -L policyOR \ sha256:set1.pcr0.policy,set2.pcr0.policy unsealed=`tpm2 unseal -p session:session.ctx -c sealkey.ctx` echo $unsealed tpm2 flushcontext session.ctx rm session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policypassword.sh000066400000000000000000000026401412464516500246410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh policypassword=policy.dat session_ctx=session.ctx o_policy_digest=policy.digest primary_key_ctx=prim.ctx key_ctx=key.ctx key_pub=key.pub key_priv=key.priv plain_txt=plain.txt signature_txt=signature.txt testpswd=testpswd cleanup() { rm -f $policypassword $session_ctx $o_policy_digest $primary_key_ctx \ $key_ctx $key_pub $key_priv $plain_txt $signature_txt tpm2 flushcontext $session_ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo "plaintext" > $plain_txt tpm2 startauthsession -S $session_ctx tpm2 policypassword -S $session_ctx -L $policypassword tpm2 flushcontext $session_ctx rm $session_ctx tpm2 createprimary -C o -c $primary_key_ctx tpm2 create -g sha256 -G ecc -u $key_pub -r $key_priv -C $primary_key_ctx \ -L $policypassword -p $testpswd tpm2 load -C $primary_key_ctx -u $key_pub -r $key_priv -c $key_ctx tpm2 sign -c $key_ctx -p $testpswd -o $signature_txt $plain_txt tpm2 verifysignature -c key.ctx -m $plain_txt -s $signature_txt tpm2 startauthsession --policy-session -S $session_ctx tpm2 policypassword -S $session_ctx -L $policypassword tpm2 sign -c $key_ctx -p session:$session_ctx+$testpswd -o $signature_txt $plain_txt tpm2 verifysignature -c key.ctx -m $plain_txt -s $signature_txt tpm2 flushcontext $session_ctx rm $session_ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policypcr.sh000066400000000000000000000023351412464516500235640ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f pcr.bin pcr.policy1 pcr.policy2 pcr.policy3 tpm2 flushcontext session.ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 clear tpm2 pcrread sha1:0,1,2+sha256:0,1,2 -o pcr.bin # Policy PCR values calculated by specifying the expected pcr data in a file tpm2 startauthsession -S session.ctx tpm2 policypcr -Q -l sha1:0,1,2+sha256:0,1,2 -S session.ctx \ -L pcr.policy1 -f pcr.bin tpm2 flushcontext session.ctx # Policy PCR values calculated by reading pcr data from the TPM tpm2 startauthsession -S session.ctx tpm2 policypcr -Q -l sha1:0,1,2+sha256:0,1,2 -S session.ctx \ -L pcr.policy2 tpm2 flushcontext session.ctx # Policy PCR values calculated by specifying digest of all PCRs directly tpm2 startauthsession -S session.ctx PCRDIGEST=`openssl dgst -sha256 -binary pcr.bin | xxd -p -c 32` tpm2 policypcr -Q -l sha1:0,1,2+sha256:0,1,2 -S session.ctx \ -L pcr.policy3 $PCRDIGEST tpm2 flushcontext session.ctx # Check if policy pcr values match for all possible methods to specify PCR diff pcr.policy1 pcr.policy2 diff pcr.policy2 pcr.policy3 exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policysecret.sh000066400000000000000000000066111412464516500242660ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh TPM_RH_OWNER=0x40000001 SEALED_SECRET=SEALED-SECRET session_ctx=session.ctx o_policy_digest=policy.digest primary_ctx=prim.ctx seal_key_pub=sealing_key.pub seal_key_priv=sealing_key.priv seal_key_ctx=sealing_key.ctx cleanup() { rm -f $session_ctx $o_policy_digest $primary_ctx $seal_key_pub $seal_key_priv\ $seal_key_ctx qual.dat tpm2 flushcontext $session_ctx 2>/dev/null || true tpm2 clear if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 clear tpm2 changeauth -c o ownerauth # Create Policy tpm2 startauthsession -S $session_ctx tpm2 policysecret -S $session_ctx -c $TPM_RH_OWNER -L $o_policy_digest ownerauth tpm2 flushcontext $session_ctx rm $session_ctx # Create and Load Object tpm2 createprimary -Q -C o -c $primary_ctx -P ownerauth tpm2 create -Q -g sha256 -u $seal_key_pub -r $seal_key_priv -C $primary_ctx \ -L $o_policy_digest -i- <<< $SEALED_SECRET tpm2 load -C $primary_ctx -u $seal_key_pub -r $seal_key_priv -c $seal_key_ctx # Satisfy policy and unseal data tpm2 startauthsession --policy-session -S $session_ctx echo -n "ownerauth" | tpm2 policysecret -S $session_ctx -c $TPM_RH_OWNER \ -L $o_policy_digest file:- unsealed=`tpm2 unseal -p"session:$session_ctx" -c $seal_key_ctx` tpm2 flushcontext $session_ctx rm $session_ctx test "$unsealed" == "$SEALED_SECRET" if [ $? != 0 ]; then echo "Failed policysecret integration test where ref object password was set." fi #Test the policy with auth reference object password not set unsealed="" tpm2 changeauth -c o -p ownerauth tpm2 startauthsession --policy-session -S $session_ctx tpm2 policysecret -S $session_ctx -c $TPM_RH_OWNER -L $o_policy_digest unsealed=`tpm2 unseal -p"session:$session_ctx" -c $seal_key_ctx` tpm2 flushcontext $session_ctx rm $session_ctx test "$unsealed" == "$SEALED_SECRET" if [ $? != 0 ]; then echo "Failed policysecret integration test for passwordless reference object." fi # # Test with policyref or qualification data # unsealed="" tpm2 clear dd if=/dev/urandom of=qual.dat bs=1 count=32 tpm2 startauthsession -S $session_ctx tpm2 policysecret -S $session_ctx -c $TPM_RH_OWNER -L $o_policy_digest \ -q qual.dat tpm2 flushcontext $session_ctx tpm2 createprimary -Q -C o -c $primary_ctx tpm2 create -Q -g sha256 -u $seal_key_pub -r $seal_key_priv -C $primary_ctx \ -L $o_policy_digest -i- <<< $SEALED_SECRET tpm2 load -C $primary_ctx -u $seal_key_pub -r $seal_key_priv -c $seal_key_ctx tpm2 startauthsession --policy-session -S $session_ctx tpm2 policysecret -S $session_ctx -c $TPM_RH_OWNER -L $o_policy_digest \ -q qual.dat unsealed=`tpm2 unseal -p"session:$session_ctx" -c $seal_key_ctx` tpm2 flushcontext $session_ctx test "$unsealed" == "$SEALED_SECRET" if [ $? != 0 ]; then echo "Failed policysecret integration test for passwordless reference object." fi # # Test with policy auth reference instead of plain password # tpm2 startauthsession -S session.ctx tpm2 policyauthvalue -S session.ctx -L policy.authval tpm2 flushcontext session.ctx tpm2 setprimarypolicy -C o -L policy.authval -g sha256 tpm2 startauthsession -S session.ctx --policy-session tpm2 startauthsession -S policy_session.ctx --policy-session tpm2 policyauthvalue -S session.ctx tpm2 policysecret -S policy_session.ctx -c o session:session.ctx tpm2 flushcontext session.ctx tpm2 flushcontext policy_session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policysigned.sh000066400000000000000000000114411412464516500242470ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f session.ctx secret.dat private.pem public.pem signature.dat \ signing_key.ctx policy.signed prim.ctx sealing_key.priv sealing_key.pub \ unsealed.dat qual.dat to_sign.bin tpm2 flushcontext $session_ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo "plaintext" > secret.dat # Create the signing authority openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem # Load the verification key and Create the policysigned policy tpm2 loadexternal -C o -G rsa -u public.pem -c signing_key.ctx # # Test with policy expiration set to zero and no other dependencies # tpm2 startauthsession -S session.ctx tpm2 policysigned -S session.ctx -c signing_key.ctx -L policy.signed tpm2 flushcontext session.ctx ## Create a sealing object to use the policysigned tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx \ -C prim.ctx -i secret.dat -L policy.signed -Q ## Unseal secret tpm2 startauthsession -S session.ctx --policy-session ### Generate signature with nonceTPM, cpHashA, policyRef and expiration set to 0 tpm2 policysigned -S session.ctx -c signing_key.ctx --raw-data to_sign.bin openssl dgst -sha256 -sign private.pem -out signature.dat to_sign.bin ### Satisfy policy tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx ### Unseal tpm2 unseal -p session:session.ctx -c sealing_key.ctx -o unsealed.dat tpm2 flushcontext session.ctx diff secret.dat unsealed.dat rm -f unsealed.dat # # Test with policy expiration set to zero and policyref/qualifier data # dd if=/dev/urandom of=qual.dat bs=1 count=32 status=none tpm2 startauthsession -S session.ctx tpm2 policysigned -S session.ctx -c signing_key.ctx -L policy.signed -q qual.dat tpm2 flushcontext session.ctx ## Create a sealing object to use the policysigned tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx \ -C prim.ctx -i secret.dat -L policy.signed -Q ## Unseal secret tpm2 startauthsession -S session.ctx --policy-session ### Generate signature with nonceTPM, cpHashA, and expiration set to 0 tpm2 policysigned -S session.ctx -c signing_key.ctx -q qual.dat \ --raw-data to_sign.bin openssl dgst -sha256 -sign private.pem -out signature.dat to_sign.bin ### Satisfy policy tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -q qual.dat tpm2 unseal -p session:session.ctx -c sealing_key.ctx -o unsealed.dat tpm2 flushcontext session.ctx diff secret.dat unsealed.dat rm -f unsealed.dat # # Test with nonceTPM # tpm2 startauthsession -S session.ctx tpm2 policysigned -S session.ctx -c signing_key.ctx -L policy.signed tpm2 flushcontext session.ctx tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx \ -C prim.ctx -i secret.dat -L policy.signed -Q ## Unseal secret tpm2 startauthsession -S session.ctx --policy-session ### Generate signature tpm2 policysigned -S session.ctx -c signing_key.ctx -x --raw-data to_sign.bin openssl dgst -sha256 -sign private.pem -out signature.dat to_sign.bin ###Satisfy the policy tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -x tpm2 unseal -p session:session.ctx -c sealing_key.ctx -o unsealed.dat tpm2 flushcontext session.ctx diff secret.dat unsealed.dat rm -f unsealed.dat # # Test with cpHashA with ECDSA signature # openssl ecparam -name prime256v1 -genkey -noout -out signing_key.priv openssl ec -in signing_key.priv -outform PEM -pubout -out signing_key.pub tpm2 loadexternal -C o -G ecc -u signing_key.pub -c signing_key_pub.ctx ## Create cpHash and policy digest tpm2 dictionarylockout -c --cphash cphash.bin tpm2 startauthsession -S session.ctx tpm2 policysigned -S session.ctx -c signing_key_pub.ctx -L policy.signed \ --cphash-input cphash.bin tpm2 flushcontext session.ctx ## Set lockout hierarchy authValue and policyAuth tpm2 changeauth -c l "password" tpm2 setprimarypolicy -C l -P "password" -L policy.signed -g sha256 tpm2 startauthsession -S session.ctx --policy-session ### Generate signature with cpHashA tpm2 policysigned -S session.ctx -c signing_key_pub.ctx --raw-data to_sign.bin \ --cphash-input cphash.bin openssl dgst -sha256 -sign signing_key.priv -out signature.dat to_sign.bin ### Satisfy policy tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f ecdsa \ -c signing_key_pub.ctx --cphash cphash.bin ### Authorize tpm2 dictionarylockout -c session:session.ctx tpm2 flushcontext session.ctx rm -f signing_key.priv signing_key.pub signing_key_pub.ctx cphash.bin \ session.ctx policy.signed to_sign.bin signature.dat exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policytemplate.sh000066400000000000000000000055751412464516500246240ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f prim.ctx template.data template.hash policy.template key.pub key.priv tpm2 flushcontext session.ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi rm -f session.ctx } trap cleanup EXIT start_up cleanup "no-shutdown" # # Restrict the primary object type created under a hierarchy # ## Create a key template tpm2 createprimary -C o -c prim.ctx --template-data template.data cat template.data | openssl dgst -sha256 -binary -out template.hash ## Create the policytemplate tpm2 startauthsession -S session.ctx -g sha256 tpm2 policytemplate -S session.ctx -L policy.template \ --template-hash template.hash tpm2 flushcontext session.ctx ## Set the owner hierarchy policy to create primary keys of specific template tpm2 setprimarypolicy -C o -g sha256 -L policy.template ## Satisfy the policy and create a primary key tpm2 startauthsession -S session.ctx -g sha256 --policy-session tpm2 policytemplate -S session.ctx --template-hash template.hash tpm2 createprimary -C o -c prim2.ctx -P session:session.ctx tpm2 flushcontext session.ctx ## Attempt to create a primary key with a different template tpm2 startauthsession -S session.ctx -g sha256 --policy-session tpm2 policytemplate -S session.ctx --template-hash template.hash trap - ERR tpm2 createprimary -C o -G ecc -c prim2.ctx -P session:session.ctx if [ $? == 0 ];then echo "ERROR: Expected tpm2 createprimary should fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx # # Restrict the object type created under a primary key # tpm2 clear ## Create a key template tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -C prim.ctx -u key.pub -r key.priv --template-data template.data -Q cat template.data | openssl dgst -sha256 -binary -out template.hash rm -f prim.ctx key.pub key.priv template.data ## Create the policytemplate tpm2 startauthsession -S session.ctx -g sha256 tpm2 policytemplate -S session.ctx -L policy.template \ --template-hash template.hash tpm2 flushcontext session.ctx ## Set the primary key auth policy to create keys of specific template tpm2 createprimary -C o -c prim.ctx -L policy.template -Q ## Satisfy the policy and create a key tpm2 startauthsession -S session.ctx -g sha256 --policy-session tpm2 policytemplate -S session.ctx --template-hash template.hash tpm2 create -C prim.ctx -u key.pub -r key.priv -P session:session.ctx -Q tpm2 flushcontext session.ctx ## Attempt to create a key with a different template tpm2 startauthsession -S session.ctx -g sha256 --policy-session tpm2 policytemplate -S session.ctx --template-hash template.hash trap - ERR tpm2 create -C prim.ctx -G ecc -u key.pub -r key.priv -P session:session.ctx if [ $? == 0 ];then echo "ERROR: Expected tpm2 createprimary should fail!" exit 1 fi trap onerror ERR tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/abrmd_policyticket.sh000066400000000000000000000054451412464516500242700ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f session.ctx secret.dat private.pem public.pem signature.dat \ signing_key.ctx policy.signed prim.ctx sealing_key.priv sealing_key.pub \ unsealed.dat qual.dat time.out tic.ket authobj.name to_sign.bin tpm2 flushcontext session.ctx 2>/dev/null || true if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" echo "plaintext" > secret.dat # # Test with policysigned # # Create the signing authority openssl genrsa -out private.pem 2048 openssl rsa -in private.pem -outform PEM -pubout -out public.pem # Load the verification key and Create the policysigned policy tpm2 loadexternal -C o -G rsa -u public.pem -c signing_key.ctx \ -n signing_key.name tpm2 startauthsession -S session.ctx tpm2 policysigned -S session.ctx -c signing_key.ctx -L policy.signed tpm2 flushcontext session.ctx # Create a sealing object to use the policysigned tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx \ -C prim.ctx -i secret.dat -L policy.signed -Q # Create a policy ticket for policysigned tpm2 startauthsession -S session.ctx --policy-session tpm2 policysigned -S session.ctx -c signing_key.ctx -x -t -500 \ --raw-data to_sign.bin openssl dgst -sha256 -sign private.pem -out signature.dat to_sign.bin tpm2 policysigned -S session.ctx -g sha256 -s signature.dat -f rsassa \ -c signing_key.ctx -x --ticket tic.ket --timeout time.out -t -500 tpm2 flushcontext session.ctx # Satisfy the policyticket and unseal the secret tpm2 startauthsession -S session.ctx --policy-session tpm2 policyticket -S session.ctx -n signing_key.name --ticket tic.ket \ --timeout time.out tpm2 unseal -p session:session.ctx -c sealing_key.ctx -o unsealed.dat tpm2 flushcontext session.ctx diff secret.dat unsealed.dat rm -f unsealed.dat # # Test with policysecret # tpm2 clear tpm2 startauthsession -S session.ctx tpm2 policysecret -S session.ctx -c o -L policy.secret tpm2 flushcontext session.ctx tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -Q -g sha256 -u sealing_key.pub -r sealing_key.priv -C prim.ctx \ -L policy.secret -i secret.dat tpm2 load -C prim.ctx -u sealing_key.pub -r sealing_key.priv -c sealing_key.ctx tpm2 startauthsession -S session.ctx --policy-session tpm2 policysecret -S session.ctx -c o -t -500 --timeout time.out \ --ticket tic.ket --nonce-tpm tpm2 flushcontext session.ctx TPM2_RH_OWNER="40000001" echo $TPM2_RH_OWNER | xxd -r -p > authobj.name tpm2 startauthsession -S session.ctx --policy-session tpm2 policyticket -S session.ctx -n authobj.name --ticket tic.ket \ --timeout time.out tpm2 unseal -p"session:session.ctx" -c sealing_key.ctx -o unsealed.dat tpm2 flushcontext session.ctx diff secret.dat unsealed.dat exit 0 tpm2-tools-5.2/test/integration/tests/activecredential.sh000066400000000000000000000031101412464516500237110ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f secret.data ek.pub ak.pub ak.name mkcred.out actcred.out ak.out \ ak.ctx session.ctx # Evict persistent handles, we want them to always succeed and never trip # the onerror trap. tpm2 evictcontrol -Q -C o -c 0x81010009 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo 12345678 > secret.data tpm2 createek -Q -c 0x81010009 -G rsa -u ek.pub tpm2 createak -C 0x81010009 -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \ -n ak.name -p akpass> ak.out file_size=`ls -l ak.name | awk {'print $5'}` loaded_key_name=`cat ak.name | xxd -p -c $file_size` # Use -c in xxd so there is no line wrapping tpm2 readpublic -c 0x81010009 -o ek.pem -f pem -Q echo "12345678" | tpm2 makecredential -Q -u ek.pem -s - -n $loaded_key_name \ -o mkcred.out -G rsa # Test the secret data matches after credential activation process tpm2 startauthsession --policy-session -S session.ctx tpm2 policysecret -S session.ctx -c e tpm2 activatecredential -Q -c ak.ctx -C 0x81010009 -i mkcred.out \ -o actcred.out -p akpass -P"session:session.ctx" tpm2 flushcontext session.ctx diff actcred.out secret.data # Capture the yaml output and verify that its the same as the name output loaded_key_name_yaml=`python << pyscript from __future__ import print_function import yaml with open('ak.out', 'r') as f: doc = yaml.safe_load(f) print(doc['loaded-key']['name']) pyscript` test "$loaded_key_name_yaml" == "$loaded_key_name" exit 0 tpm2-tools-5.2/test/integration/tests/attestation.sh000066400000000000000000000062151412464516500227530ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh handle_ek=0x81010009 context_ak=ak.ctx handle_nv=0x1500018 ek_alg=rsa ak_alg=rsa digestAlg=sha256 signAlg=rsassa ownerpw=ownerpass endorsepw=endorsepass akpw=akpass rand_pcr_value=6ea40aa7267bb71251c1de1c3605a3df759b86b22fa9f62aa298d4197cd88a38 debug_pcr=16 debug_pcr_list=15,16,22 file_input_data=secret.data file_input_key=nv.data output_ek_pub_pem=ekpub.pem output_ek_pub=ek.pub output_ak_pub_pem=akpub.pem output_ak_pub=ak.pub output_ak_pub_name=ak.name output_mkcredential=mkcred.out output_actcredential=actcred.out output_quote=quote.out output_quotesig=quotesig.out output_quotepcr=quotepcr.out cleanup() { rm -f $file_input_data $file_input_key $output_ek_pub $output_ek_pub_pem \ $output_ak_pub $output_ak_pub_pem $output_ak_pub_name $output_mkcredential \ $output_actcredential $output_quote $output_quotesig $output_quotepcr \ $context_ak rand.out session.ctx tpm2 pcrreset -Q $debug_pcr tpm2 evictcontrol -Q -C o -c $handle_ek -P "$ownerpw" 2>/dev/null || true tpm2 evictcontrol -Q -C o -c $context_ak -P "$ownerpw" 2>/dev/null || true tpm2 nvundefine -Q $handle_nv -C o \ -P "$ownerpw" 2>/dev/null || true if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo 12345678 > $file_input_data echo 1234567890123456789012345678901 > $file_input_key getrandom() { loaded_randomness=`tpm2 getrandom --hex $1` } tpm2 changeauth -c o "$ownerpw" tpm2 changeauth -c e "$endorsepw" # Key generation tpm2 createek -Q -c $handle_ek -G $ek_alg -u $output_ek_pub_pem -f pem \ -w "$ownerpw" -P "$endorsepw" tpm2 readpublic -Q -c $handle_ek -o $output_ek_pub tpm2 createak -Q -C $handle_ek -c $context_ak -G $ak_alg -g $digestAlg \ -s $signAlg -u $output_ak_pub_pem -f pem -n $output_ak_pub_name -p "$akpw" \ -P "$endorsepw" tpm2 readpublic -Q -c $context_ak -o $output_ak_pub # Validate keys (registrar) file_size=`ls -l $output_ak_pub_name | awk {'print $5'}` loaded_key_name=`cat $output_ak_pub_name | xxd -p -c $file_size` tpm2 makecredential -Q -T none -u $output_ek_pub -s $file_input_data \ -n $loaded_key_name -o $output_mkcredential tpm2 startauthsession --policy-session -S session.ctx tpm2 policysecret -S session.ctx -c e $endorsepw tpm2 activatecredential -Q -c $context_ak -C $handle_ek \ -i $output_mkcredential -o $output_actcredential -p "$akpw" \ -P "session:session.ctx" tpm2 flushcontext session.ctx diff $file_input_data $output_actcredential # Quoting tpm2 pcrreset -Q $debug_pcr tpm2 pcrextend -Q $debug_pcr:sha256=$rand_pcr_value tpm2 pcrread -Q getrandom 20 tpm2 quote -Q -c $context_ak -l $digestAlg:$debug_pcr_list \ -q $loaded_randomness -m $output_quote -s $output_quotesig -o $output_quotepcr \ -g $digestAlg -p "$akpw" # Verify quote tpm2 checkquote -Q -u $output_ak_pub_pem -m $output_quote -s $output_quotesig \ -f $output_quotepcr -g $digestAlg -q $loaded_randomness # Save U key from verifier tpm2 nvdefine -Q $handle_nv -C o -s 32 -a "ownerread|ownerwrite" \ -p "indexpass" -P "$ownerpw" tpm2 nvwrite -Q $handle_nv -C o -P "$ownerpw" -i $file_input_key tpm2 nvread -Q $handle_nv -C o -s 32 -P "$ownerpw" exit 0 tpm2-tools-5.2/test/integration/tests/certify.sh000066400000000000000000000011761412464516500220620ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx certify.ctx certify.pub certify.priv certify.name \ attest.out sig.out &>/dev/null if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c primary.ctx tpm2 create -Q -g sha256 -G rsa -u certify.pub -r certify.priv -C primary.ctx tpm2 load -Q -C primary.ctx -u certify.pub -r certify.priv -n certify.name \ -c certify.ctx tpm2 certify -Q -c primary.ctx -C certify.ctx -g sha256 -o attest.out -s sig.out exit 0 tpm2-tools-5.2/test/integration/tests/certifycreation.sh000066400000000000000000000034161412464516500236060ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx creation.data creation.digest creation.ticket rsa.pub \ rsa.priv signature.bin attestation.bin sslpub.pem qual.dat sec_key.pub \ sec_key.priv sec_key.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -C o -c primary.ctx --creation-data creation.data \ -d creation.digest -t creation.ticket -Q tpm2 create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx -c signing_key.ctx -Q tpm2 readpublic -c signing_key.ctx -f pem -o sslpub.pem tpm2 certifycreation -C signing_key.ctx -c primary.ctx -d creation.digest \ -t creation.ticket -g sha256 -o signature.bin --attestation attestation.bin \ -f plain -s rsassa openssl dgst -verify sslpub.pem -keyform pem -sha256 -signature signature.bin \ attestation.bin # # Test with qualifier data # dd if=/dev/urandom of=qual.dat bs=1 count=32 tpm2 certifycreation -C signing_key.ctx -c primary.ctx -d creation.digest \ -t creation.ticket -g sha256 -o signature.bin --attestation attestation.bin \ -f plain -s rsassa -q qual.dat openssl dgst -verify sslpub.pem -keyform pem -sha256 -signature signature.bin \ attestation.bin # # Test certification with non primary keys # tpm2 create -C primary.ctx -u sec_key.pub -r sec_key.priv -t creation.ticket \ -d creation.digest --creation-data creation.data -Q tpm2 load -C primary.ctx -u sec_key.pub -r sec_key.priv -c sec_key.ctx -Q tpm2 certifycreation -C signing_key.ctx -c sec_key.ctx -d creation.digest \ -t creation.ticket -g sha256 -o signature.bin --attestation attestation.bin \ -f plain -s rsassa openssl dgst -verify sslpub.pem -keyform pem -sha256 -signature signature.bin \ attestation.bin exit 0 tpm2-tools-5.2/test/integration/tests/changeauth.sh000066400000000000000000000027021412464516500225200ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm key.ctx key.pub key.priv primary.ctx shut_down } trap cleanup EXIT start_up ownerPasswd=abc123 endorsePasswd=abc123 lockPasswd=abc123 new_ownerPasswd=newpswd new_endorsePasswd=newpswd new_lockPasswd=newpswd tpm2 clear tpm2 changeauth -c o $ownerPasswd tpm2 changeauth -c e $endorsePasswd tpm2 changeauth -c l $lockPasswd tpm2 changeauth -c o -p $ownerPasswd $new_ownerPasswd tpm2 changeauth -c e -p $endorsePasswd $new_endorsePasswd tpm2 changeauth -c l -p $lockPasswd $new_lockPasswd tpm2 clear $new_lockPasswd tpm2 changeauth -c o $ownerPasswd tpm2 changeauth -c e $endorsePasswd tpm2 changeauth -c l $lockPasswd tpm2 clear $lockPasswd # Test changing an objects auth tpm2 createprimary -Q -C o -c primary.ctx tpm2 create -Q -C primary.ctx -p foo -u key.pub -r key.priv tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -c key.ctx tpm2 changeauth -C primary.ctx -p foo -c key.ctx -r new.priv bar # Test changing an NV index auth tpm2 startauthsession -S session.ctx tpm2 policycommandcode -S session.ctx -L policy.nvchange TPM2_CC_NV_ChangeAuth tpm2 flushcontext session.ctx NVIndex=0x1500015 tpm2 nvdefine $NVIndex -C o -s 32 -a "authread|authwrite" -L policy.nvchange tpm2 startauthsession --policy-session -S session.ctx tpm2 policycommandcode -S session.ctx -L policy.nvchange TPM2_CC_NV_ChangeAuth tpm2 changeauth -p session:session.ctx -c $NVIndex newindexauth exit 0 tpm2-tools-5.2/test/integration/tests/changeeps.sh000066400000000000000000000021321412464516500223430ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 changeauth -c p -p testpassword 2>/dev/null || true rm -f primary.ctx key.pub key.priv key.ctx key.name if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -Q -C e -c primary.ctx tpm2 create -Q -C primary.ctx -u key.pub -r key.priv tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx tpm2 flushcontext -t # # Test that the object cannot be loaded after change the endorsement seed # which causes all transient objects created under the endorsement hierarchy # to be invalidated. # tpm2 changeeps trap - ERR tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx # # Test with non null platform hierarchy auth # trap onerror ERR tpm2 changeauth -c p testpassword tpm2 createprimary -Q -C e -c primary.ctx tpm2 create -Q -C primary.ctx -u key.pub -r key.priv tpm2 changeeps -p testpassword trap - ERR tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx exit 0 tpm2-tools-5.2/test/integration/tests/changepps.sh000066400000000000000000000021441412464516500223610ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 changeauth -c p -p testpassword 2>/dev/null || true rm -f primary.ctx key.pub key.priv key.ctx key.name if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -Q -C p -c primary.ctx tpm2 create -Q -C primary.ctx -u key.pub -r key.priv tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx tpm2 flushcontext -t # # Test that the object cannot be loaded after change the Platform seed # which causes all transient objects created under the platform hierarchy # to be invalidated. # tpm2 changepps trap - ERR tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx # # Test with non null platform hierarchy auth # trap onerror ERR tpm2 changeauth -c p testpassword tpm2 createprimary -Q -C p -c primary.ctx -P testpassword tpm2 create -Q -C primary.ctx -u key.pub -r key.priv tpm2 changepps -p testpassword trap - ERR tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx exit 0 tpm2-tools-5.2/test/integration/tests/checkquote.sh000066400000000000000000000047221412464516500225500ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh handle_ek=0x81010009 handle_ak=0x8101000a ek_alg=rsa ak_alg=rsa digestAlg=sha256 signAlg=rsassa akpw=akpass ak_ctx=ak.ctx output_ek_pub_pem=ekpub.pem output_ak_pub_pem=akpub.pem output_ak_pub_name=ak.name output_quote=quote.out output_quotesig=quotesig.out output_quotepcr=quotepcr.out cleanup() { rm -f $output_ek_pub_pem $output_ak_pub_pem $output_ak_pub_name \ $output_quote $output_quotesig $output_quotepcr rand.out $ak_ctx \ pcr.bin tpm2 pcrreset 16 tpm2 evictcontrol -C o -c $handle_ek 2>/dev/null || true tpm2 evictcontrol -C o -c $handle_ak 2>/dev/null || true if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down echo "shutdown" fi } trap cleanup EXIT start_up cleanup "no-shut-down" getrandom() { tpm2 getrandom -o rand.out $1 local file_size=`ls -l rand.out | awk {'print $5'}` loaded_randomness=`cat rand.out | xxd -p -c $file_size` } # Key generation tpm2 createek -c $handle_ek -G $ek_alg -u $output_ek_pub_pem -f pem tpm2 createak -C $handle_ek -c $ak_ctx -G $ak_alg -g $digestAlg -s $signAlg \ -u $output_ak_pub_pem -f pem -n $output_ak_pub_name -p "$akpw" tpm2 evictcontrol -Q -c $ak_ctx $handle_ak # Quoting getrandom 20 tpm2 quote -c $handle_ak -l sha256:15,16,22 -q $loaded_randomness \ -m $output_quote -s $output_quotesig -o $output_quotepcr -g $digestAlg -p "$akpw" # Verify quote tpm2 checkquote -u $output_ak_pub_pem -m $output_quote -s $output_quotesig \ -f $output_quotepcr -g $digestAlg -q $loaded_randomness # Verify EC tpm2 createek -G ecc -c ecc.ek tpm2 createak -C ecc.ek -c ecc.ak -G ecc -g sha256 -s ecdsa tpm2 readpublic -c ecc.ak -f pem -o ecc.ak.pem tpm2 getrandom -o nonce.bin 20 tpm2 quote -c ecc.ak -l sha256:15,16,22 -q nonce.bin -m quote.bin -s quote.sig -o quote.pcr -g sha256 tpm2 checkquote -u ecc.ak.pem -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin # Verify that tss format works tpm2 readpublic -c ecc.ak -f tss -o ecc.ak.tss tpm2 checkquote -u ecc.ak.tss -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin # Verify the tpmt format works tpm2 readpublic -c ecc.ak -f tpmt -o ecc.ak.tpmt tpm2 checkquote -u ecc.ak.tpmt -m quote.bin -s quote.sig -f quote.pcr -g sha256 -q nonce.bin # Verify that the plain tpm2_pcrread output can be passed to the checkquote tool tpm2 pcrread sha256:15,16,22 -o pcr.bin tpm2 checkquote -u ecc.ak.tpmt -m quote.bin -s quote.sig -g sha256 -q nonce.bin \ -f pcr.bin -l sha256:15,16,22 exit 0 tpm2-tools-5.2/test/integration/tests/clear.sh000066400000000000000000000013071412464516500214770ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { shut_down } trap cleanup EXIT start_up lockPasswd=lockoutpass platPasswd=platformpass #Test tpm2 clear works with blank lockout auth as default tpm2 clear #Test tpm2 clear works with non-empy lockout auth as default tpm2 changeauth -c l $lockPasswd tpm2 clear $lockPasswd #Test tpm2 clear works with non-empy lockout auth and specified auth hierarchy tpm2 changeauth -c l $lockPasswd tpm2 clear -c l $lockPasswd #Test tpm2 clear works with non-empy platform auth and specified auth hierarchy tpm2 changeauth -c p $platPasswd tpm2 clear -c p $platPasswd #Undo change of platform auth tpm2 changeauth -c p -p $platPasswd exit 0 tpm2-tools-5.2/test/integration/tests/clearcontrol.sh000066400000000000000000000004021412464516500230730ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 clearcontrol tpm2 clear shut_down } trap cleanup EXIT start_up tpm2 clearcontrol -C l s trap - ERR tpm2 clear trap onerror ERR tpm2 clearcontrol tpm2 clear exit 0 tpm2-tools-5.2/test/integration/tests/clockrateadjust.sh000066400000000000000000000020571412464516500235760ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 changeauth -c o -p newowner 2>/dev/null || true tpm2 changeauth -c p -p newplatform 2>/dev/null || true rm -f clock.yaml if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up tpm2 clockrateadjust s tpm2 clockrateadjust ss tpm2 clockrateadjust sss tpm2 clockrateadjust f tpm2 clockrateadjust ff tpm2 clockrateadjust fff # validate hierarchies and passwords tpm2 changeauth -c o newowner tpm2 changeauth -c p newplatform tpm2 clockrateadjust -c o -p newowner ss tpm2 clockrateadjust -c p -p newplatform ff trap - err tpm2 clockrateadjust -c o -p newowner ssss if [ $? -eq 0 ]; then echo "expected ssss to fail" exit 1 fi tpm2 clockrateadjust -c o -p newowner sfss if [ $? -eq 0 ]; then echo "expected ssss to fail" exit 1 fi tpm2 clockrateadjust -c o -p newowner sfs if [ $? -eq 0 ]; then echo "expected sfs to fail" exit 1 fi tpm2 clockrateadjust -c o -p newowner qqq if [ $? -eq 0 ]; then echo "expected qqq to fail" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/commandaudit.sh000066400000000000000000000036311412464516500230600ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f \ prim.ctx signing_key.ctx signing_key.pub signing_key.priv \ att.data att.sig if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 clear # # Audit counter should be zero at reset # AUDIT_COUNTER_ZERO=0x0 tpm2 getcap properties-variable | \ grep TPM2_PT_AUDIT_COUNTER_1 | awk -F " " '{print $2}' | \ grep $AUDIT_COUNTER_ZERO # # Audit counter increments when setting up the audit digest algorithm # other than the default. In simulator the default is sha512. # tpm2 setcommandauditstatus -g sha256 AUDIT_COUNTER_ONE=0x1 tpm2 getcap properties-variable | \ grep TPM2_PT_AUDIT_COUNTER_1 | awk -F " " '{print $2}' | \ grep $AUDIT_COUNTER_ONE tpm2 createprimary -C o -c prim.ctx tpm2 create -C prim.ctx -c signing_key.ctx -u signing_key.pub -r signing_key.priv # # Check TPM2_CC_SetCommandAuditStatus is included by default # tpm2 getcommandauditdigest -g sha256 -f plain -m att.data -s att.sig \ -c signing_key.ctx TPM2_CC_SetCommandAuditStatus=00000140 diff -B \ <( echo $TPM2_CC_SetCommandAuditStatus | xxd -r -p | \ openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Check if TPM2_CC_GetRandom is added to the setlist # tpm2 setcommandauditstatus TPM2_CC_GetRandom tpm2 getcommandauditdigest -g sha256 -f plain -m att.data -s att.sig \ -c signing_key.ctx TPM2_CC_GetRandom=0000017B diff -B \ <( echo $TPM2_CC_SetCommandAuditStatus$TPM2_CC_GetRandom | \ xxd -r -p | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Check TPM2_CC_GetRandom is removed from the audit list # tpm2 setcommandauditstatus --clear-list TPM2_CC_GetRandom tpm2 getcommandauditdigest -g sha256 -f plain -m att.data -s att.sig \ -c signing_key.ctx diff -B \ <( echo $TPM2_CC_SetCommandAuditStatus | xxd -r -p | \ openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) exit 0 tpm2-tools-5.2/test/integration/tests/create.sh000066400000000000000000000070311412464516500216540ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f key.pub key.priv policy.bin out.pub key.ctx if [ $(ina "$@" "keep-context") -ne 0 ]; then rm -f context.out fi rm -f key*.ctx out.yaml if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 createprimary -Q -C o -g sha1 -G rsa -c context.out # Keep the algorithm specifiers mixed to test friendly and raw # values. for gAlg in `populate_hash_algs`; do for GAlg in rsa keyedhash ecc aes; do echo "tpm2 create -Q -C context.out -g $gAlg -G $GAlg -u key.pub \ -r key.priv" tpm2 create -Q -C context.out -g $gAlg -G $GAlg -u key.pub -r key.priv cleanup "keep-context" "no-shut-down" done done cleanup "keep-context" "no-shut-down" policy_orig=f28230c080bbe417141199e36d18978228d8948fc10a6a24921b9eba6bb1d988 echo "$policy_orig" | xxd -r -p > policy.bin tpm2 create -C context.out -g sha256 -G rsa -L policy.bin -u key.pub \ -r key.priv -a 'sign|fixedtpm|fixedparent|sensitivedataorigin' > out.pub policy_new=$(yaml_get_kv out.pub "authorization policy") test "$policy_orig" == "$policy_new" # # Test the extended format specifiers # # aes128cfb (mandatory for PCClient TPMs) tpm2 create -Q -C context.out -g sha256 -G aes128cfb -u key.pub -r key.priv tpm2 load -Q -C context.out -u key.pub -r key.priv -c key1.ctx tpm2 readpublic -c key1.ctx > out.yaml keybits=$(yaml_get_kv out.yaml "sym-keybits") mode=$(yaml_get_kv out.yaml "sym-mode" "value") test "$keybits" -eq "128" test "$mode" == "cfb" # aes256ofb (if supported) if is_alg_supported aes256ofb; then mode="$(populate_alg_modes $strongest_aes | head -n1)" # e.g. aes128ecb tpm2 create -Q -C context.out -g sha256 -G aes256ofb -u key.pub -r key.priv tpm2 load -Q -C context.out -u key.pub -r key.priv -c key2.ctx tpm2 readpublic -c key2.ctx > out.yaml keybits=$(yaml_get_kv out.yaml "sym-keybits") mode=$(yaml_get_kv out.yaml "sym-mode" "value") test "$keybits" -eq "256" test "$mode" == "ofb" fi exit 0 # # Test scheme support # for alg in "rsa1024:rsaes" "ecc384:ecdaa4-sha256"; do if is_alg_supported $alg; then tpm2 create -Q -C context.out -g sha256 -G "$alg" -u key.pub -r key.priv fi done # Test createloaded support tpm2 create -C context.out -u key.pub -r key.priv -c key.ctx tpm2 readpublic -c key.ctx 2>/dev/null # Test that creation data has the specified outside info tpm2 createprimary -C o -c prim.ctx -Q dd if=/dev/urandom of=outside.info bs=1 count=32 tpm2 create -C prim.ctx -u key.pub -r key.priv --creation-data creation.data \ -q outside.info -Q xxd -p creation.data | tr -d '\n' | grep `xxd -p outside.info | tr -d '\n'` # Test that selected pcrs digest is present in the creation data tpm2 pcrread sha256:0 -o pcr_data.bin tpm2 create -C prim.ctx -u key.pub -r key.priv --creation-data creation.data \ -l sha256:0 -Q xxd -p creation.data | tr -d '\n' | \ grep `cat pcr_data.bin | openssl dgst -sha256 -binary | xxd -p | tr -d '\n'` # Test if additional sessions can be specified tpm2 clear tpm2 createprimary -C o -c prim.ctx -Q tpm2 startauthsession -S audit_session.ctx --audit-session tpm2 startauthsession -S enc_session.ctx --hmac-session -c prim.ctx tpm2 create -C prim.ctx -u key.pub -r key.priv -p apple \ -S enc_session.ctx \ -S audit_session.ctx tpm2 flushcontext audit_session.ctx tpm2 flushcontext enc_session.ctx # Test public key output tpm2_create -C primary.ctx -u obj.pub -r obj.priv -f pem -o obj.pem openssl rsa -noout -text -inform PEM -in obj.pem -pubin exit 0 tpm2-tools-5.2/test/integration/tests/createak.sh000066400000000000000000000023261412464516500221720ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f ek.pub ak.pub ak.name ak.name ak.log # Evict persistent handles, we want them to always succeed and never trip # the onerror trap. tpm2 evictcontrol -Q -C o -c 0x8101000b 2>/dev/null || true tpm2 evictcontrol -Q -C o -c 0x8101000c 2>/dev/null || true # clear tpm state tpm2 clear if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 createek -Q -c 0x8101000b -G rsa -u ek.pub tpm2 createak -Q -C 0x8101000b -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \ -n ak.name -q ak.qname # Validate the qname tpm2 readpublic -c ak.ctx -q ak.qname2 diff ak.qname ak.qname2 # Find a vacant persistent handle tpm2 createak -C 0x8101000b -c ak.ctx -G rsa -g sha256 -s rsassa -u ak.pub \ -n ak.name tpm2 evictcontrol -c ak.ctx > ak.log phandle=`yaml_get_kv ak.log "persistent-handle"` tpm2 evictcontrol -Q -C o -c $phandle # Test tpm2 createak with endorsement password cleanup "no-shut-down" tpm2 changeauth -c e endauth tpm2 createek -Q -P endauth -c 0x8101000b -G rsa -u ek.pub tpm2 createak -Q -P endauth -C 0x8101000b -c ak.ctx -G rsa -u ak.pub -n ak.name exit 0 tpm2-tools-5.2/test/integration/tests/createek.sh000066400000000000000000000024771412464516500222050ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f ek.pub ek.log ek.template ek.nonce ek.ctx # Evict persistent handles, we want them to always succeed and never trip # the onerror trap. tpm2 evictcontrol -Q -C o -c 0x81010005 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 createek -c 0x81010005 -G rsa -u ek.pub cleanup "no-shut-down" tpm2 createek -c - -G rsa -u ek.pub > ek.log phandle=`yaml_get_kv ek.log "persistent-handle"` tpm2 evictcontrol -Q -C o -c $phandle cleanup "no-shut-down" tpm2 createek -G rsa -u ek.pub -c ek.ctx cleanup "no-shut-down" ek_nonce_index=0x01c00003 ek_template_index=0x01c00004 # Define RSA EK template nbytes=$(wc -c ${abs_srcdir}/test/integration/fixtures/ek-template-default.bin | awk {'print $1'}) tpm2 nvdefine -Q $ek_template_index -C o -s $nbytes \ -a "ownerread|policywrite|ownerwrite" tpm2 nvwrite -Q $ek_template_index -C o \ -i ${abs_srcdir}/test/integration/fixtures/ek-template-default.bin # Define RSA EK nonce echo -n -e '\0' > ek.nonce tpm2 nvdefine -Q $ek_nonce_index -C o -s 1 \ -a "ownerread|policywrite|ownerwrite" tpm2 nvwrite -Q $ek_nonce_index -C o -i ek.nonce tpm2 createek -t -G rsa -u ek.pub -c ek.ctx cleanup "no-shut-down" exit 0 tpm2-tools-5.2/test/integration/tests/createpolicy.sh000066400000000000000000000022771412464516500231030ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh ###this script use for test the implementation tpm2 createpolicy cleanup() { rm -f pcr.in policy.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up declare -A digestlengths=\ ([sha1]=20 [sha256]=32) declare -A expected_policy_digest=\ ([sha1]=f28230c080bbe417141199e36d18978228d8948fc10a6a24921b9eba6bb1d988 [sha256]=33e36e786c878632494217c3f490e74ca0a3a122a8a4f3c5302500df3b32b3b8) tpm2 pcrread -V sha1 for halg in ${!digestlengths[@]} do cleanup "no-shut-down" # Create file containing expected PCR value head -c $((${digestlengths[$halg]} - 1)) /dev/zero > pcr.in echo -n -e '\x03' >> pcr.in tpm2 createpolicy --policy-pcr -l $halg:0 -f pcr.in -L policy.out # Test the policy creation hashes against expected if [ $(xxd -p policy.out | tr -d '\n' ) != \ "${expected_policy_digest[${halg}]}" ]; then echo "Failure: Creating Policy Digest with PCR policy for index 0 and \ ${halg} pcr index hash" echo "Got: $(xxd -p policy.out | tr -d '\n')" echo "Expected: ${expected_policy_digest[${halg}]}" exit 1 fi done exit 0 tpm2-tools-5.2/test/integration/tests/createprimary.sh000066400000000000000000000073551412464516500232710ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up cleanup() { rm -f policy.bin obj.pub pub.out primary.ctx if [ $(ina "$@" "keep-context") -ne 0 ]; then rm -f context.out fi if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT cleanup "no-shut-down" # Keep the algorithm specifiers mixed to test friendly and raw # values. for gAlg in `populate_hash_algs 'and alg != "keyedhash"'`; do for GAlg in rsa xor ecc aes; do echo tpm2 createprimary -Q -g $gAlg -G $GAlg -c context.out tpm2 createprimary -Q -g $gAlg -G $GAlg -c context.out cleanup "no-shut-down" "keep-context" for Atype in o e n; do tpm2 createprimary -Q -C $Atype -g $gAlg -G $GAlg -c context.out cleanup "no-shut-down" "keep-context" done done done policy_orig=f28230c080bbe417141199e36d18978228d8948fc10a6a24921b9eba6bb1d988 #test for createprimary objects with policy authorization structures echo -n "$policy_orig" | xxd -r -p > policy.bin tpm2 createprimary -Q -C o -G rsa -g sha256 -c context.out -L policy.bin \ -a 'restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin' tpm2 readpublic -c context.out > pub.out policy_new=$(yaml_get_kv pub.out "authorization policy") test "$policy_orig" == "$policy_new" # # Test that -u can be specified to pass a TPMU_PUBLIC_ID union # # in this case TPM2B_PUBLIC_KEY_RSA (256 bytes of zero) printf '\x00\x01' > ud.1 dd if=/dev/zero bs=256 count=1 of=ud.2 cat ud.1 ud.2 > unique.dat tpm2 createprimary -C o -G rsa2048:aes128cfb -g sha256 -c prim.ctx \ -a "restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|\ noda" -u unique.dat test -f prim.ctx rm -f prim.ctx # test the case with ECC key type with MAX_ECC_KEY_BITS=256 printf '\x20\x00' > ecc_param_buf_size dd if=/dev/urandom bs=32 count=1 of=ecc_param_buf cat ecc_param_buf_size ecc_param_buf ecc_param_buf_size ecc_param_buf > unique.dat tpm2 createprimary -C o -G ecc -g sha256 -c prim.ctx -u unique.dat \ -a "restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda" test -f prim.ctx rm -f prim.ctx # test the case with RSA and unique data specified via stdin dd if=/dev/urandom bs=256 count=1 status=none | \ tpm2 createprimary -C o -G rsa -g sha256 -c prim.ctx -u - \ -a "restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda" test -f prim.ctx rm -f prim.ctx # test the case with ECC and unique data specified via stdin dd if=/dev/urandom bs=96 count=1 status=none | \ tpm2 createprimary -C o -G ecc -g sha256 -c prim.ctx -u - \ -a "restricted|decrypt|fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda" test -f prim.ctx rm -f prim.ctx # Test that -g/-G do not need to be specified. tpm2 createprimary -Q -c context.out # Test that -o does not need to be specified. tpm2 createprimary -Q # Test that creation data has the specified outside info dd if=/dev/urandom of=outside.info bs=1 count=32 tpm2 createprimary -C o -c context.out --creation-data creation.data \ -q outside.info xxd -p creation.data | tr -d '\n' | grep `xxd -p outside.info | tr -d '\n'` # Test that selected pcrs digest is present in the creation data tpm2 pcrread sha256:0 -o pcr_data.bin tpm2 createprimary -C o -c context.out --creation-data creation.data \ -l sha256:0 xxd -p creation.data | tr -d '\n' | \ grep `cat pcr_data.bin | openssl dgst -sha256 -binary | xxd -p | tr -d '\n'` # Test for session leaks BEFORE=$(tpm2 getcap handles-loaded-session; tpm2 getcap handles-saved-session) tpm2 createprimary -Q AFTER=$(tpm2 getcap handles-loaded-session; tpm2 getcap handles-saved-session) test "${BEFORE}" = "${AFTER}" # Test pem key tpm2 createprimary -f pem -o public.pem openssl rsa -noout -text -inform PEM -in public.pem -pubin exit 0 tpm2-tools-5.2/test/integration/tests/dictionarylockout.sh000066400000000000000000000015221412464516500241560ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause ###this script use for test the implementation tpm2 dictionarylockout source helpers.sh out=out.yaml cleanup() { rm -f $out shut_down } trap cleanup EXIT start_up tpm2 dictionarylockout -Q -V -c &>/dev/null tpm2 dictionarylockout -s -n 5 -t 6 -l 7 tpm2 getcap properties-variable > $out v=$(yaml_get_kv "$out" "TPM2_PT_MAX_AUTH_FAIL") if [ $v -ne 5 ];then echo "Failure: setting up the number of allowed tries in the lockout \ parameters" exit 1 fi v=$(yaml_get_kv "$out" "TPM2_PT_LOCKOUT_INTERVAL") if [ $v -ne 6 ];then echo "Failure: setting up the lockout period in the lockout parameters" exit 1 fi v=$(yaml_get_kv "$out" "TPM2_PT_LOCKOUT_RECOVERY") if [ $v -ne 7 ];then echo "Failure: setting up the lockout recovery period in the lockout \ parameters" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/duplicate.sh000066400000000000000000000135031412464516500223640ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx new_parent.prv new_parent.pub new_parent.ctx policy.dat \ session.dat key.prv key.pub key.ctx duppriv.bin dupseed.dat key2.prv \ key2.pub key2.ctx sym_key_in.bin cleartext.txt secret.bin decrypted.txt \ primary.pub rsa-priv.pem rsa.pub rsa.priv rsa.dpriv rsa.seed rsa-pub.pem rsa.sig if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up create_duplication_policy() { tpm2 startauthsession -Q -S session.dat tpm2 policycommandcode -Q -S session.dat -L policy.dat TPM2_CC_Duplicate tpm2 flushcontext -Q session.dat rm session.dat } start_duplication_session() { tpm2 startauthsession -Q --policy-session -S session.dat tpm2 policycommandcode -Q -S session.dat -L policy.dat TPM2_CC_Duplicate } end_duplication_session() { tpm2 flushcontext -Q session.dat rm session.dat } dump_duplication_session() { rm session.dat } dd if=/dev/urandom of=sym_key_in.bin bs=1 count=16 status=none tpm2 createprimary -Q -C o -g sha256 -G rsa -c primary.ctx # Create a new parent, we will only use the public portion tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub -a "decrypt|fixedparent|fixedtpm|restricted|\ sensitivedataorigin" # Create the key we want to duplicate create_duplication_policy tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r key.prv -u key.pub \ -L policy.dat -a "sensitivedataorigin|sign|decrypt" tpm2 load -Q -C primary.ctx -r key.prv -u key.pub -c key.ctx tpm2 loadexternal -Q -C o -u new_parent.pub -c new_parent.ctx ## Null parent, Null Sym Alg start_duplication_session tpm2 duplicate -Q -C null -c key.ctx -G null -p "session:session.dat" \ -r dupprv.bin -s dupseed.dat end_duplication_session ## Null Sym Alg start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key.ctx -G null \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## Null parent start_duplication_session tpm2 duplicate -Q -C null -c key.ctx -G aes -i sym_key_in.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## AES Sym Alg, user supplied key start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key.ctx -G aes -i sym_key_in.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## AES Sym Alg, no user supplied key start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key.ctx -G aes -o sym_key_out.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## Repeat the tests with a key that requires encrypted duplication tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r key2.prv -u key2.pub \ -L policy.dat -a "sensitivedataorigin|sign|decrypt|encryptedduplication" tpm2 load -Q -C primary.ctx -r key2.prv -u key2.pub -c key2.ctx ## AES Sym Alg, user supplied key start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key2.ctx -G aes -i sym_key_in.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## AES Sym Alg, no user supplied key start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key2.ctx -G aes -o sym_key_out.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat end_duplication_session ## External RSA key, wrapped for the primary key tpm2 readpublic -c primary.ctx -o primary.pub openssl genrsa -out rsa-priv.pem openssl rsa -in rsa-priv.pem -pubout > rsa-pub.pem tpm2 duplicate \ --tcti none \ -U primary.pub \ -G rsa \ -k rsa-priv.pem \ -u rsa.pub \ -r rsa.dpriv \ -s rsa.seed tpm2 import \ -C primary.ctx \ -G rsa \ -i rsa.dpriv \ -s rsa.seed \ -u rsa.pub \ -r rsa.priv # validate that TPM signatures with this imported key are acceptable to OpenSSL tpm2 load \ -C primary.ctx \ -c rsa.ctx \ -u rsa.pub \ -r rsa.priv echo foo | tpm2 sign \ -c rsa.ctx \ -o rsa.sig \ -f plain echo foo | openssl dgst \ -sha256 \ -verify rsa-pub.pem \ -signature rsa.sig ## External RSA key, with a password authorization policy echo magicwords > cleartext.txt openssl pkeyutl \ -encrypt \ -pubin \ -inkey rsa-pub.pem \ -in cleartext.txt \ -out secret.bin tpm2 startauthsession -S session.dat tpm2 policypassword -S session.dat -L policy.dat tpm2 duplicate \ --tcti none \ -U primary.pub \ -G rsa \ -k rsa-priv.pem \ -u rsa.pub \ -r rsa.dpriv \ -s rsa.seed \ -L policy.dat \ -p secretpassword tpm2 import \ -C primary.ctx \ -G rsa \ -i rsa.dpriv \ -s rsa.seed \ -u rsa.pub \ -r rsa.priv # validate that TPM can decrypt messages with this imported key tpm2 load \ -C primary.ctx \ -c rsa.ctx \ -u rsa.pub \ -r rsa.priv \ tpm2 startauthsession -S session.dat --policy-session tpm2 policypassword -S session.dat -L policy.dat cat secret.bin | tpm2 rsadecrypt \ -c rsa.ctx \ -p session:session.dat+secretpassword \ > decrypted.txt cmp cleartext.txt decrypted.txt trap - ERR ## Attempt to decrypt without the password or policy cat secret.bin | tpm2 rsadecrypt \ -c rsa.ctx \ -p session:session.dat if [ $? -eq 0 ]; then echo "Expected \"tpm2 rsadecrypt\" to fail without password." exit 1 fi cat secret.bin | tpm2 rsadecrypt \ -c rsa.ctx if [ $? -eq 0 ]; then echo "Expected \"tpm2 rsadecrypt\" to fail without policy." exit 1 fi ## Null parent - should fail (TPM_RC_HIERARCHY) start_duplication_session tpm2 duplicate -Q -C null -c key2.ctx -G aes -i sym_key_in.bin \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat if [ $? -eq 0 ]; then echo "Expected \"tpm2 duplicate -C null \" to fail." exit 1 fi dump_duplication_session ## Null Sym Alg - should fail (TPM_RC_SYMMETRIC) start_duplication_session tpm2 duplicate -Q -C new_parent.ctx -c key2.ctx -G null \ -p "session:session.dat" -r dupprv.bin -s dupseed.dat if [ $? -eq 0 ]; then echo "Expected \"tpm2 duplicate -G null \" to fail." exit 1 fi dump_duplication_session exit 0 tpm2-tools-5.2/test/integration/tests/ecc.sh000066400000000000000000000043261412464516500211470ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f pass1_ecc.q pass2_ecc.q ecc.ctr if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # TPM2_EC_Ephemeral ## Check if commit counter is zero on first invocation tpm2 ecephemeral -u pass1_ecc.q -t pass1_ecc.ctr ecc256 xxd -p pass1_ecc.ctr | grep 0000 ## Check if commit counter increments to 1 on second invocation tpm2 ecephemeral -u pass2_ecc.q -t pass2_ecc.ctr ecc256 xxd -p pass2_ecc.ctr | grep 0001 # TPM2_Commit ## Check if commit counter in incremented after successful execution of commit tpm2 createprimary -C o -c prim.ctx -Q tpm2 create -C prim.ctx -c commit_key.ctx -u commit_key.pub -r commit_key.priv \ -G ecc256:ecdaa tpm2 commit -c commit_key.ctx -t commit.ctr --eccpoint-K K.bin \ --eccpoint-L L.bin -u E.bin xxd -p commit.ctr | grep 0002 # TPM2_ECDH_KeyGen ## Check if ecdhkeygen creates ephemeral key with loaded ECC key of type ECDAA tpm2 ecdhkeygen -u ecc256ecdaa.pub -o ecc256ecdaa.priv -c commit_key.ctx ## Check if ecdhkeygen creates ephemeral key with loaded ECC key of type ECDH tpm2 create -C prim.ctx -c ecdh_key.ctx -u ecdh_key.pub -r ecdh_key.priv \ -G ecc256:ecdh tpm2 ecdhkeygen -u ecc256ecdh.pub -o ecc256ecdh.priv -c ecdh_key.ctx # TPM2_ECDH_ZGen ## Check if the recovered Z point matches tpm2 ecdhzgen -u ecc256ecdh.pub -o ecdhZgen.dat -c ecdh_key.ctx diff ecdhZgen.dat ecc256ecdh.priv # TPM2_ZGen_2Phase ## Check if output Z points are generated using separate commit count values tpm2 zgen2phase -c ecdh_key.ctx --static-public ecc256ecdh.pub \ --ephemeral-public pass1_ecc.q -t 0 --output-Z1 pass1.z1 --output-Z2 pass1.z2 tpm2 zgen2phase -c ecdh_key.ctx --static-public ecc256ecdh.pub \ --ephemeral-public pass2_ecc.q -t 1 --output-Z1 pass2.z1 --output-Z2 pass2.z2 tpm2 zgen2phase -c ecdh_key.ctx --static-public ecc256ecdh.pub \ --ephemeral-public E.bin -t 2 --output-Z1 pass3.z1 --output-Z2 pass3.z2 ## Check to ensure the Z1 points are always the same value diff pass1.z1 pass2.z1 diff pass2.z1 pass3.z1 ## Check to ensure the Z2 points are different trap - ERR diff pass1.z2 pass2.z2 diff pass1.z2 pass3.z2 diff pass2.z2 pass3.z2 trap onerror ERR exit 0 tpm2-tools-5.2/test/integration/tests/encryptdecrypt.sh000066400000000000000000000156641412464516500235030ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx decrypt.ctx key.pub key.priv key.name decrypt.out \ decrypt2.out encrypt.out encrypt2.out secret.dat secret2.dat \ iv.dat iv2.dat key128.ctx plain.dec128.tpm plain.dec256.tpm plain.enc128.tpm \ plain.enc256.tpm sym128.key key256.ctx plain.dec128.ssl plain.dec256.ssl \ plain.enc128.ssl plain.enc256.ssl plain.txt sym256.key if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" if ! is_cmd_supported "EncryptDecrypt"; then echo "Command EncryptDecrypt is not supported by your device, skipping..." skip_test fi echo "12345678" > secret.dat tpm2 clear -Q tpm2 createprimary -Q -C e -g sha1 -G rsa -c primary.ctx tpm2 create -Q -g sha256 -G aes -u key.pub -r key.priv -C primary.ctx tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c decrypt.ctx tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out secret.dat tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out encrypt.out # Test using stdin/stdout cat secret.dat | tpm2 encryptdecrypt -c decrypt.ctx | tpm2 encryptdecrypt \ -c decrypt.ctx -d > secret2.dat # test using IVs dd if=/dev/urandom of=iv.dat bs=16 count=1 cat secret.dat | tpm2 encryptdecrypt -c decrypt.ctx --iv iv.dat | \ tpm2 encryptdecrypt -c decrypt.ctx --iv iv.dat:iv2.dat -d > secret2.dat cmp secret.dat secret2.dat # Test using specified object modes tpm2 create -Q -G aes128cbc -u key.pub -r key.priv -C primary.ctx rm decrypt.ctx tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c decrypt.ctx # We need to perform cbc on blocksize of 16 echo -n 1234567812345678 > secret.dat # specified mode tpm2 encryptdecrypt -Q -c decrypt.ctx -G cbc --iv=iv.dat -o encrypt.out \ secret.dat # Unspecified mode (figure out via readpublic) tpm2 encryptdecrypt -Q -d -c decrypt.ctx --iv iv.dat -o decrypt.out encrypt.out cmp secret.dat decrypt.out # Test that iv looping works tpm2 encryptdecrypt -Q -c decrypt.ctx -G cbc --iv=iv.dat:iv2.dat \ -o encrypt.out secret.dat tpm2 encryptdecrypt -Q -c decrypt.ctx -G cbc --iv=iv2.dat -o encrypt2.out \ secret.dat tpm2 encryptdecrypt -Q -d -c decrypt.ctx --iv iv.dat -o decrypt.out encrypt.out tpm2 encryptdecrypt -Q -d -c decrypt.ctx --iv iv2.dat -o decrypt2.out \ encrypt2.out cmp secret.dat decrypt.out cmp secret.dat decrypt2.out # Test that input data sizes greater than TPM2_MAX_BUFFER or 1024 work dd if=/dev/zero bs=1 count=2048 status=none of=secret2.dat cat secret2.dat | tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out encrypt.out cmp secret2.dat decrypt.out # Test that last block in input data shorter than block length has pkcs7 padding dd if=/dev/zero bs=1 count=2050 status=none of=secret2.dat cat secret2.dat | tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out -e tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out encrypt.out ## Last block is short 14 or hex 0E trailing bytes echo 0e0e0e0e0e0e0e0e0e0e0e0e0e0e | xxd -r -p >> secret2.dat cmp secret2.dat decrypt.out # Test that pkcs7 padding is added as last block for block length aligned inputs dd if=/dev/zero bs=1 count=2048 status=none of=secret2.dat cat secret2.dat | tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out -e tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out encrypt.out ## Last block is short 14 or hex 0E trailing bytes echo 10101010101010101010101010101010 | xxd -r -p >> secret2.dat cmp secret2.dat decrypt.out # Test pkcs7 padding is stripped from input data is shorter than block length dd if=/dev/zero bs=1 count=2050 status=none of=secret2.dat cat secret2.dat | tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out -e tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out -e encrypt.out cmp secret2.dat decrypt.out # Test that pkcs7 pad is stripped off last block for block length aligned inputs dd if=/dev/zero bs=1 count=2048 status=none of=secret2.dat cat secret2.dat | tpm2 encryptdecrypt -Q -c decrypt.ctx -o encrypt.out -e tpm2 encryptdecrypt -Q -c decrypt.ctx -d -o decrypt.out -e encrypt.out cmp secret2.dat decrypt.out # Negative that bad mode fails trap - ERR # mode CFB should fail, since the object was explicitly created with mode CBC tpm2 encryptdecrypt -Q -c decrypt.ctx -G cfb --iv=iv.dat -o encrypt.out \ secret.dat # set the error handler for checking interoperability with openssl trap onerror ERR # Testing interoperability with openssl - Also exercises PKCS7 padding dd if=/dev/urandom of=sym128.key bs=1 count=16 dd if=/dev/urandom of=sym256.key bs=1 count=32 tpm2 loadexternal -C n -G aes -r sym128.key -c key128.ctx tpm2 loadexternal -C n -G aes -r sym256.key -c key256.ctx echo "plaintext" > plain.txt ## Encrypt with ossl and tpm for cbc mode that requires padding ### Key size = 128 openssl enc -in plain.txt -out plain.enc128.ssl -K `xxd -c 128 -p sym128.key` \ -aes-128-cbc -iv 0 tpm2 encryptdecrypt -c key128.ctx -o plain.enc128.tpm -e -G cbc plain.txt diff plain.enc128.ssl plain.enc128.tpm ### Key size = 256 openssl enc -in plain.txt -out plain.enc256.ssl -K `xxd -c 256 -p sym256.key` \ -aes-256-cbc -iv 0 tpm2 encryptdecrypt -c key256.ctx -o plain.enc256.tpm -e -G cbc plain.txt diff plain.enc256.ssl plain.enc256.tpm ## Decrypt ciphertext from tpm in openssl and vice versa ### Key size = 128 tpm2 encryptdecrypt -c key128.ctx -o plain.dec128.tpm -e \ -G cbc -d plain.enc128.ssl diff plain.dec128.tpm plain.txt openssl enc -d -in plain.enc128.tpm -out plain.dec128.ssl -aes-128-cbc -iv 0 \ -K `xxd -c 128 -p sym128.key` diff plain.dec128.ssl plain.txt ### Key size = 256 tpm2 encryptdecrypt -c key256.ctx -o plain.dec256.tpm -e \ -G cbc -d plain.enc256.ssl diff plain.dec256.tpm plain.txt openssl enc -d -in plain.enc256.tpm -out plain.dec256.ssl -aes-256-cbc -iv 0 \ -K `xxd -c 256 -p sym256.key` diff plain.dec256.ssl plain.txt ## Encrypt with ossl and tpm for cfb mode that does not apply padding ### Key size = 128 openssl enc -in plain.txt -out plain.enc128.ssl -K `xxd -c 128 -p sym128.key` \ -aes-128-cfb -iv 0 tpm2 encryptdecrypt -c key128.ctx -o plain.enc128.tpm -G cfb plain.txt diff plain.enc128.ssl plain.enc128.tpm ### Key size = 256 openssl enc -in plain.txt -out plain.enc256.ssl -K `xxd -c 256 -p sym256.key` \ -aes-256-cfb -iv 0 tpm2 encryptdecrypt -c key256.ctx -o plain.enc256.tpm -G cfb plain.txt diff plain.enc256.ssl plain.enc256.tpm ## Decrypt ciphertext from tpm in openssl and vice versa ### Key size = 128 tpm2 encryptdecrypt -c key128.ctx -o plain.dec128.tpm \ -G cfb -d plain.enc128.ssl diff plain.dec128.tpm plain.txt openssl enc -d -in plain.enc128.tpm -out plain.dec128.ssl -aes-128-cfb -iv 0 \ -K `xxd -c 128 -p sym128.key` diff plain.dec128.ssl plain.txt ### Key size = 256 tpm2 encryptdecrypt -c key256.ctx -o plain.dec256.tpm \ -G cfb -d plain.enc256.ssl diff plain.dec256.tpm plain.txt openssl enc -d -in plain.enc256.tpm -out plain.dec256.ssl -aes-256-cfb -iv 0 \ -K `xxd -c 256 -p sym256.key` diff plain.dec256.ssl plain.txt exit 0 tpm2-tools-5.2/test/integration/tests/eventlog.sh000066400000000000000000000030061412464516500222320ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause set -E shopt -s expand_aliases alias python=${PYTHON-python} yaml_validate() { python -c 'import yaml,sys; yaml.safe_load(sys.stdin)' } expect_fail() { $@ if [ $? -eq 0 ]; then echo "failing test case passed" exit 1; fi } expect_pass() { $@ | yaml_validate if [ $? -ne 0 ]; then echo "passing test case failed" exit 1; fi } expect_fail tpm2 eventlog expect_fail tpm2 eventlog foo expect_fail tpm2 eventlog foo bar expect_fail tpm2 eventlog ${srcdir}/test/integration/fixtures/event-bad.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/specid-vendordata.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-uefivar.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-uefiaction.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-uefiservices.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-uefi-sha1-log.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-bootorder.bin expect_pass tpm2 eventlog ${srcdir}/test/integration/fixtures/event-postcode.bin # Make sure that --eventlog-version=2 works on complete TPM2 logs expect_pass tpm2 eventlog --eventlog-version=2 ${srcdir}/test/integration/fixtures/event-arch-linux.bin expect_pass tpm2 eventlog --eventlog-version=2 ${srcdir}/test/integration/fixtures/event-gce-ubuntu-2104-log.bin exit $? tpm2-tools-5.2/test/integration/tests/evictcontrol.sh000066400000000000000000000025331412464516500231260ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx decrypt.ctx key.pub key.priv key.name decrypt.out \ encrypt.out secret.dat key.dat evict.log primary.ctx key.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c primary.ctx tpm2 create -Q -g sha256 -G aes -u key.pub -r key.priv -C primary.ctx tpm2 load -Q -C primary.ctx -u key.pub -r key.priv -n key.name -c key.dat # Load the context into a specific handle, delete it tpm2 evictcontrol -Q -c key.dat 0x81010003 tpm2 evictcontrol -Q -c 0x81010003 0x81010003 # Load the context into a specific handle, delete it without an explicit -p tpm2 evictcontrol -Q -C o -c key.dat 0x81010003 tpm2 evictcontrol -Q -C o -c 0x81010003 # Load the context into an available handle, delete it tpm2 evictcontrol -C o -c key.dat > evict.log phandle=$(yaml_get_kv evict.log "persistent-handle") tpm2 evictcontrol -Q -C o -c $phandle yaml_verify evict.log # verify that platform hierarchy auto selection for persistent handle works tpm2 createprimary -C p -c primary.ctx tpm2 create -C primary.ctx -c key.ctx tpm2 evictcontrol -C p -c key.ctx > evict.log phandle=$(yaml_get_kv evict.log persistent-handle) tpm2 evictcontrol -C p -c $phandle exit 0 tpm2-tools-5.2/test/integration/tests/flushcontext.sh000066400000000000000000000013621412464516500231400ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up cleanup() { rm -f saved_session.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT cleanup "no-shut-down" tpm2 clear # Test for flushing the specified handle tpm2 createprimary -Q -C o -g sha256 -G rsa # tpm2-abrmd may save the transient object and restore it when using res=`tpm2 getcap handles-transient` if [ -n "$res" ]; then tpm2 flushcontext -Q -c 0x80000000 fi # Test for flushing a transient object tpm2 createprimary -Q -C o -g sha256 -G rsa tpm2 flushcontext -Q -t # Test for flushing a loaded session tpm2 createpolicy -Q --policy-session --policy-pcr -l sha256:0 tpm2 flushcontext -Q -l cleanup "no-shut-down" exit 0 tpm2-tools-5.2/test/integration/tests/getcap.sh000066400000000000000000000014421412464516500216540ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up out=out.yaml cleanup() { rm -f $out shut_down } trap cleanup EXIT function yaml_to_list() { python << pyscript from __future__ import print_function import sys import yaml with open("$1") as f: try: y = yaml.safe_load(f) print(' '.join(y)) except yaml.YAMLError as exc: sys.exit(exc) pyscript } tpm2 getcap -l > $out caplist=$(yaml_to_list $out) for c in $caplist; do tpm2 getcap "$c" > $out yaml_verify $out done; # negative tests trap - ERR # Regression test, ensure that getcap -c never accepts prefix matches tpm2 getcap -Q --capability="comma" 2>/dev/null if [ $? -eq -1 ]; then echo "Expected \"tpm2 getcap -Q --capability=\"comma\"\" to fail." exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/getekcertificate.sh000066400000000000000000000076051412464516500237220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause if [ `uname` == "FreeBSD" ]; then exit 77 fi source helpers.sh cleanup() { rm -f test_rsa_ek.pub rsa_ek_cert.bin stdout_rsa_ek_cert.bin \ test_ecc_ek.pub ecc_ek_cert.bin stdout_ecc_ek_cert.bin shut_down } trap cleanup EXIT start_up # Check connectivity if [ -z "$(curl -V 2>/dev/null)" ]; then echo "curl is not not installed. Skipping connection check." else if [ "$(curl --silent --output /dev/null --write-out %{http_code} \ 'https://ekop.intel.com/')" != '200' ]; then echo 'No connection to https://ekop.intel.com/' exit 77 fi fi # Sample RSA ek public from a real platform echo "013a0001000b000300b20020837197674484b3f81a90cc8d46a5d724fd52 d76e06520b64f2a1da1b331469aa00060080004300100800000000000100 c320e2f244a8601aacf3e01d26c665249935562de1da197e9e7f076c4696 13cfb653e98ec2c386fc1d133f2c8c6cc338b732f0b208bd838a877a3e5b bc3e1d4084e835c7c8906a1c05b4d2d30fdbebc1dbad950fa6b165bd4b6a 864603146164c0c4f59d489011ef1f928deea6e90061f3d375e564627315 1ef622252098be1a4ab01dc0a12227c609fdaceb115af408d4693a6f4991 9774695b0c12bc18a1ff7120a7337b2fb5f1951d8bb7f094d5b554c11c95 23b30729fe64787d0a13b9e630488dab4dfd86634a5270ec72fcc5a44dc6 79a8f32938dd8197e29dae839f5b4ca0f5de27c9522c23c54e1c2ce57859 525118bd4470b18180eef78ae4267bcd" | xxd -r -p > test_rsa_ek.pub # Get ek certificate and output to file tpm2 getekcertificate -u test_rsa_ek.pub -x -X -o rsa_ek_cert.bin # Test that stdoutput is the same tpm2 getekcertificate -u test_rsa_ek.pub -x -X > stdout_rsa_ek_cert.bin # stdout file should match cmp rsa_ek_cert.bin stdout_rsa_ek_cert.bin # Retrieved certificate should be valid tpm2 loadexternal -C e -u test_rsa_ek.pub -c rsa_key.ctx tpm2 readpublic -c rsa_key.ctx -f pem -o test_rsa_ek.pem openssl x509 -pubkey -in rsa_ek_cert.bin -noout -out test_ek.pem diff test_rsa_ek.pem test_ek.pem # Sample ECC ek public from a real platform echo "007a0023000b000300b20020837197674484b3f81a90cc8d46a5d724fd52 d76e06520b64f2a1da1b331469aa00060080004300100003001000206d8e 7630ee5d11e566e80299bfb9e43cec8c44f70bc8ad81b50f690a3deb7498 002021a536c8fef7482313d7f4517f11c9f2b4cd424cbc8fe9094b895668 51fe0853" | xxd -r -p > test_ecc_ek.pub # Get ecc certificate and output to file tpm2 getekcertificate -u test_ecc_ek.pub -x -X -o ecc_ek_cert.bin # Test that stdoutput is the same tpm2 getekcertificate -u test_ecc_ek.pub -x -X > stdout_ecc_ek_cert.bin # stdout file should match cmp ecc_ek_cert.bin stdout_ecc_ek_cert.bin # Retrieved certificate should be valid tpm2 loadexternal -C e -u test_ecc_ek.pub -c ecc_key.ctx tpm2 readpublic -c ecc_key.ctx -f pem -o test_ecc_ek.pem openssl x509 -pubkey -in ecc_ek_cert.bin -noout -out test_ek.pem diff test_ecc_ek.pem test_ek.pem # Retrieve EK certificates from NV indices RSA_EK_CERT_NV_INDEX=0x01C00002 ECC_EK_CERT_NV_INDEX=0x01C0000A define_ek_cert_nv_index() { file_size=`ls -l $1 | awk {'print $5'}` tpm2 nvdefine $2 -C p -s $file_size \ -a 'ppwrite|ppread|ownerread|authread|no_da|platformcreate' tpm2 nvwrite -C p -i $1 $2 } ## ECC only INTC certificate from NV index openssl x509 -in ecc_ek_cert.bin -out ecc_ek_cert.der -outform DER define_ek_cert_nv_index ecc_ek_cert.der $ECC_EK_CERT_NV_INDEX tpm2 getekcertificate -o nv_ecc_ek_cert.der diff nv_ecc_ek_cert.der ecc_ek_cert.der ## RSA only INTC certificate from NV index tpm2 nvundefine -C p $ECC_EK_CERT_NV_INDEX openssl x509 -in rsa_ek_cert.bin -out rsa_ek_cert.der -outform DER define_ek_cert_nv_index rsa_ek_cert.der $RSA_EK_CERT_NV_INDEX tpm2 getekcertificate -o nv_rsa_ek_cert.der diff nv_rsa_ek_cert.der rsa_ek_cert.der rm nv_rsa_ek_cert.der nv_ecc_ek_cert.der -f ## RSA & ECC INTC certificates from NV index define_ek_cert_nv_index ecc_ek_cert.der $ECC_EK_CERT_NV_INDEX tpm2 getekcertificate -o nv_rsa_ek_cert.der -o nv_ecc_ek_cert.der diff nv_rsa_ek_cert.der rsa_ek_cert.der diff nv_ecc_ek_cert.der ecc_ek_cert.der exit 0 tpm2-tools-5.2/test/integration/tests/getpolicydigest.sh000066400000000000000000000006741412464516500236160ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f policy.out test.policy if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Create a reference policy and compare tpm2 startauthsession -S session.ctx tpm2 policypassword -S session.ctx -L test.policy tpm2 getpolicydigest -S session.ctx -o policy.out tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/getrandom.sh000066400000000000000000000024211412464516500223670ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f random.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # test file output tpm2 getrandom -o random.out 32 s=`ls -l random.out | awk {'print $5'}` test $s -eq 32 #test stdout tpm2 getrandom --hex 4 > random.out s=`ls -l random.out | awk {'print $5'}` test $s -eq 8 yaml_verify random.out # test stdout and -Q tpm2 getrandom -Q --hex 4 > random.out s=`ls -l random.out | awk {'print $5'}` test $s -eq 0 # test if multiple sessions can be specified tpm2 createprimary -C o -c prim.ctx -Q tpm2 startauthsession -S audit_session.ctx --audit-session tpm2 startauthsession -S enc_session.ctx --hmac-session --tpmkey-context prim.ctx tpm2 sessionconfig enc_session.ctx --enable-encrypt tpm2 getrandom 8 -S enc_session.ctx -S audit_session.ctx # negative tests trap - ERR # larger than any known hash size should fail tpm2 getrandom 2000 &> /dev/null if [ $? -eq 0 ]; then echo "tpm2 getrandom should fail with too big of request" exit 1 fi # verify that tpm2 getrandom requires a TCTI ./tools/tpm2 getrandom -T none &> /dev/null if [ $? -eq 0 ]; then echo "tpm2 getrandom should fail with tcti: \"none\"" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/gettestresult.sh000066400000000000000000000005261412464516500233310ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tempfile=$(mktemp) # Verify that tests have succeeded tpm2 gettestresult > "${tempfile}" yaml_get_kv "${tempfile}" "status" | grep "success" exit 0 tpm2-tools-5.2/test/integration/tests/gettime.sh000066400000000000000000000005531412464516500220510ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f attest.sig attest.data } trap cleanup EXIT start_up tpm2 createprimary -C e -c primary.ctx tpm2 create -G rsa -u rsa.pub -r rsa.priv -C primary.ctx tpm2 load -C primary.ctx -u rsa.pub -r rsa.priv -c rsa.ctx tpm2 gettime -c rsa.ctx -o attest.sig --attestation attest.data exit 0 tpm2-tools-5.2/test/integration/tests/hash.sh000066400000000000000000000040721412464516500213360ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #this script is for hash case testing source helpers.sh ticket_file=ticket.out hash_out_file=hash.out hash_in_file=hash.in out=out.yaml cleanup() { rm -f $ticket_file $hash_out_file $hash_in_file $out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "T0naX0u123abc" > $hash_in_file # Test with ticket and hash output files (binary) and verify that the output # hash is correct. Ticket is not stable and changes run to run, don't verify it. tpm2 hash -C e -g sha1 -o $hash_out_file -t $ticket_file $hash_in_file expected=`shasum -a 1 $hash_in_file | awk '{print $1}'` actual=`cat $hash_out_file | xxd -p -c 20` test "$expected" == "$actual" cleanup "no-shut-down" # Test platform hierarchy with multiple files & verify output against sha256sum # Test a file redirection as well. Output files are binary. echo "T0naX0u123abc" > $hash_in_file tpm2 hash -C p -g sha256 -o $hash_out_file -t $ticket_file < $hash_in_file expected=`shasum -a 256 $hash_in_file | awk '{print $1}'` actual=`cat $hash_out_file | xxd -p -c 32` test "$expected" == "$actual" cleanup "no-shut-down" # Test stdout output as well as no options. # Validate that hash outputs are in hex as expected. tpm_hash_val=`echo 1234 | tpm2 hash -C n --hex` sha1sum_val=`echo 1234 | shasum -a 1 | cut -d\ -f 1-2 | tr -d '[:space:]'` if [ "$tpm_hash_val" != "$sha1sum_val" ]; then echo "Expected tpm and sha1sum to produce same hashes." echo "Got:" echo " tpm2 hash: $tpm_hash_val" echo " sha1sum: $sha1sum_val" exit 1 fi # Test a file that cannot be done in 1 update call. # The tpm works on a 1024 block size. dd if=/dev/urandom of=$hash_in_file bs=2093 count=1 2>/dev/null tpm_hash_val=`tpm2 hash --hex $hash_in_file` sha1sum_val=`shasum -a 1 $hash_in_file | cut -d\ -f 1-2 | tr -d '[:space:]'` if [ "$tpm_hash_val" != "$sha1sum_val" ]; then echo "Expected tpm and sha1sum to produce same hashes" echo "Got:" echo " tpm2 hash: $tpm_hash_val" echo " sha1sum: $sha1sum_val" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/hierarchycontrol.sh000066400000000000000000000043051412464516500237710ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up if [ "$TPM2TOOLS_TEST_PERSISTENT" = false ]; then echo "Skipping persistent test (requiring a TPM reset)." echo "To execute this test, set TPM2TOOLS_TEST_PERSISTENT=true or configure " \ "with --enable-persistent" skip_test fi cleanup "no-shut-down" # Storage hierarchy tpm2 hierarchycontrol -C p shEnable set tpm2 hierarchycontrol -C p shEnable clear tpm2 hierarchycontrol -C p shEnable set tpm2 hierarchycontrol -C o shEnable clear # Endorsement hierarchy tpm2 hierarchycontrol -C p ehEnable set tpm2 hierarchycontrol -C p ehEnable clear tpm2 hierarchycontrol -C p ehEnable set tpm2 hierarchycontrol -C e ehEnable clear # Platform NV tpm2 hierarchycontrol -C p phEnableNV set tpm2 hierarchycontrol -C p phEnableNV clear tpm2 hierarchycontrol -C p phEnableNV set # Platform hierarchy tpm2 hierarchycontrol -C p phEnable clear # 0 the handler trap - ERR # ERROR: phEnable may not be 1 using this command tpm2 hierarchycontrol -C p phEnable set # EROOR: Only platform hierarchy handle can be specified for 1 tpm2 hierarchycontrol -C o shEnable set tpm2 hierarchycontrol -C o ehEnable set tpm2 hierarchycontrol -C o phEnable set tpm2 hierarchycontrol -C o phEnableNV set tpm2 hierarchycontrol -C e shEnable set tpm2 hierarchycontrol -C e ehEnable set tpm2 hierarchycontrol -C e phEnable set tpm2 hierarchycontrol -C e phEnableNV set # ERROR: Permanent handle lockout not supported by this command tpm2 hierarchycontrol -C l shEnable set tpm2 hierarchycontrol -C l ehEnable set tpm2 hierarchycontrol -C l phEnable set tpm2 hierarchycontrol -C l phEnableNV set tpm2 hierarchycontrol -C l shEnable clear tpm2 hierarchycontrol -C l ehEnable clear tpm2 hierarchycontrol -C l phEnable clear tpm2 hierarchycontrol -C l phEnableNV clear # ERROR: Only platform and its authorization can be specified for 0 tpm2 hierarchycontrol -C o ehEnable clear tpm2 hierarchycontrol -C o phEnable clear tpm2 hierarchycontrol -C o phEnableNV clear tpm2 hierarchycontrol -C e shEnable clear tpm2 hierarchycontrol -C e phEnable clear tpm2 hierarchycontrol -C e phEnableNV clear exit 0 tpm2-tools-5.2/test/integration/tests/hmac.sh000066400000000000000000000052751412464516500213310ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=rsa alg_create_key=hmac handle_hmac_key=0x81010013 file_primary_key_ctx=primary.ctx file_hmac_key_pub=key.pub file_hmac_key_priv=key.priv file_hmac_key_name=name.dat file_hmac_key_ctx=key.ctx file_hmac_output=hmac.out file_hmac_key_handle=key.handle file_input_data=secret.data cleanup() { rm -f $file_primary_key_ctx $file_hmac_key_pub $file_hmac_key_priv \ $file_hmac_key_name $file_hmac_output ticket.out if [ $(ina "$@" "keep-context") -ne 0 ]; then rm -f $file_hmac_key_ctx $file_input_data # attempt to evict the hmac persistent key handle, but don't cause failures # if this fails as it may not be loaded. tpm2 evictcontrol -c $file_hmac_key_handle 2>/dev/null || true fi if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -G $alg_create_key -u $file_hmac_key_pub -r $file_hmac_key_priv \ -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_hmac_key_pub \ -r $file_hmac_key_priv -n $file_hmac_key_name -c $file_hmac_key_ctx # verify that persistent object can be used via a serialized handle tpm2 evictcontrol -C o -c $file_hmac_key_ctx -o $file_hmac_key_handle cat $file_input_data | tpm2 hmac -Q -c $file_hmac_key_handle \ -o $file_hmac_output cleanup "keep-context" "no-shut-down" # Test large file, ie sequence hmac'ing. dd if=/dev/urandom of=$file_input_data bs=2093 count=1 2>/dev/null tpm2 hmac -Q -c $file_hmac_key_ctx -o $file_hmac_output $file_input_data ####handle test rm -f $file_hmac_output cleanup "no-shut-down" # Test stdin echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -G $alg_create_key -u $file_hmac_key_pub -r $file_hmac_key_priv \ -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_hmac_key_pub \ -r $file_hmac_key_priv -n $file_hmac_key_name -c $file_hmac_key_ctx cat $file_input_data | tpm2 hmac -Q -c $file_hmac_key_ctx -o $file_hmac_output # test ticket option cat $file_input_data | tpm2 hmac -Q -c $file_hmac_key_ctx -o $file_hmac_output \ -t ticket.out test -f ticket.out # test no output file cat $file_input_data | tpm2 hmac -c $file_hmac_key_ctx 1>/dev/null # verify that silent is indeed silent stdout=`cat $file_input_data | tpm2 hmac -Q -c $file_hmac_key_ctx` if [ -n "$stdout" ]; then echo "Expected no output when run in quiet mode, got\"$stdout\"" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/import.sh000066400000000000000000000170701412464516500217270ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f import_key.ctx import_key.name import_key.priv import_key.pub \ parent.ctx plain.dec.ssl plain.enc plain.txt sym.key import_rsa_key.pub \ import_rsa_key.priv import_rsa_key.ctx import_rsa_key.name private.pem \ public.pem plain.rsa.enc plain.rsa.dec public.pem data.in.raw \ data.in.digest data.out.signed ticket.out ecc.pub ecc.priv ecc.name \ ecc.ctx private.ecc.pem public.ecc.pem passfile aes.key policy.dat \ aes.priv aes.pub sealdata seal.pub seal.priv seal.ctx unsealdata hmackey \ hmac.pub hmac.priv hmac.ctx hmac-tpm2.out hmac-ossl.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up run_aes_import_test() { dd if=/dev/urandom of=sym.key bs=1 count=$3 2>/dev/null #Symmetric Key Import Test echo "tpm2 import -Q -G aes -g "$name_alg" -i sym.key -C $1 \ -u import_key.pub -r import_key.priv" tpm2 import -Q -G aes -g "$name_alg" -i sym.key -C $1 -u import_key.pub \ -r import_key.priv tpm2 load -Q -C $1 -u import_key.pub -r import_key.priv -n import_key.name \ -c import_key.ctx echo "plaintext" > "plain.txt" if is_cmd_supported "EncryptDecrypt"; then tpm2 encryptdecrypt -c import_key.ctx -o plain.enc plain.txt openssl enc -in plain.enc -out plain.dec.ssl -d -K `xxd -c 256 -p sym.key` \ -iv 0 -$2 diff plain.txt plain.dec.ssl else tpm2 readpublic -c import_key.ctx >out.pub alg=$(yaml_get_kv out.pub "sym-alg" "value") if [ "$alg" != "aes" ]; then echo "Algorithm parsed from tpm2 readpublic is '$alg' but should be \ 'aes'" exit 1 fi rm out.pub fi rm import_key.ctx } run_rsa_import_test() { #Asymmetric Key Import Test openssl genrsa -out private.pem $2 openssl rsa -in private.pem -pubout > public.pem # Test an import without the parent public info data to force a readpublic tpm2 import -Q -G rsa -g "$name_alg" -i private.pem -C $1 \ -u import_rsa_key.pub -r import_rsa_key.priv tpm2 load -Q -C $1 -u import_rsa_key.pub -r import_rsa_key.priv \ -n import_rsa_key.name -c import_rsa_key.ctx openssl rsa -in private.pem -out public.pem -outform PEM -pubout openssl pkeyutl -encrypt -inkey public.pem -pubin -in plain.txt \ -out plain.rsa.enc tpm2 rsadecrypt -c import_rsa_key.ctx -o plain.rsa.dec plain.rsa.enc diff plain.txt plain.rsa.dec # test verifying a sigature with the imported key, ie sign in tpm and # verify with openssl echo "data to sign" > data.in.raw shasum -a 256 data.in.raw | awk '{ print "000000 " $1 }' | xxd -r -c 32 > \ data.in.digest tpm2 sign -Q -c import_rsa_key.ctx -g sha256 -d -f plain \ -o data.out.signed data.in.digest openssl dgst -verify public.pem -keyform pem -sha256 -signature \ data.out.signed data.in.raw # Sign with openssl and verify with TPM openssl dgst -sha256 -sign private.pem -out data.out.signed data.in.raw # Verify with the TPM tpm2 verifysignature -Q -c import_rsa_key.ctx -g sha256 -m data.in.raw \ -f rsassa -s data.out.signed -t ticket.out rm import_rsa_key.ctx } run_ecc_import_test() { # # Test loading an OSSL PEM format ECC key, and verifying a signature # external to the TPM # # # Generate a Private and Public ECC pem file # openssl ecparam -name $2 -genkey -noout -out private.ecc.pem openssl ec -in private.ecc.pem -out public.ecc.pem -pubout # Generate a hash to sign echo "data to sign" > data.in.raw shasum -a 256 data.in.raw | awk '{ print "000000 " $1 }' | xxd -r -c 32 > \ data.in.digest tpm2 import -Q -G ecc -g "$name_alg" -i private.ecc.pem -C $1 -u ecc.pub \ -r ecc.priv tpm2 load -Q -C $1 -u ecc.pub -r ecc.priv -n ecc.name -c ecc.ctx # Sign in the TPM and verify with OSSL tpm2 sign -Q -c ecc.ctx -g sha256 -d -f plain -o data.out.signed \ data.in.digest openssl dgst -verify public.ecc.pem -keyform pem -sha256 \ -signature data.out.signed data.in.raw # Sign with openssl and verify with TPM. openssl dgst -sha256 -sign private.ecc.pem -out data.out.signed data.in.raw tpm2 verifysignature -Q -c ecc.ctx -g sha256 -m data.in.raw -f ecdsa \ -s data.out.signed rm ecc.ctx } run_rsa_import_passin_test() { if [ "$3" != "stdin" ]; then tpm2 import -Q -G rsa -i "$2" -C "$1" \ -u "import_rsa_key.pub" -r "import_rsa_key.priv" \ --passin "$3" else tpm2 import -Q -G rsa -i "$2" -C "$1" \ -u "import_rsa_key.pub" -r "import_rsa_key.priv" \ --passin "$3" < "$4" fi; } run_aes_policy_import_test() { dd if=/dev/urandom of=aes.key bs=16 count=1 dd if=/dev/urandom of=policy.dat bs=32 count=1 tpm2 import -C "$1" -G aes -i aes.key -L policy.dat -u aes.pub -r aes.priv tpm2 load -C "$1" -u aes.priv -u aes.pub -r aes.priv -c aes.ctx trap - ERR echo 'foo' | tpm2 encryptdecrypt -c aes.ctx -o plain.rsa.dec plain.rsa.enc if [ $? -eq 0 ]; then echo "expected tpm2 encryptdecrypt to fail" exit 1 fi trap onerror ERR } run_keyedhash_seal_import_test() { dd if=/dev/urandom of=sealdata bs=128 count=1 tpm2 import -C "$1" -G keyedhash -i sealdata -u seal.pub -r seal.priv tpm2 load -C "$1" -u seal.pub -r seal.priv -c seal.ctx tpm2 unseal -c seal.ctx -o unsealdata cmp sealdata unsealdata } run_keyedhash_hmac_import_test() { dd if=/dev/urandom of=hmackey bs=64 count=1 hexkey=$(xxd -p -c 256 < hmackey) tpm2 import -C "$1" -G hmac -i hmackey -u hmac.pub -r hmac.priv tpm2 load -C "$1" -u hmac.pub -r hmac.priv -c hmac.ctx echo -n "test data" | tpm2 hmac -g sha256 -c hmac.ctx -o hmac-tpm2.out echo -n "test data" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$hexkey" -binary -out hmac-ossl.out cmp hmac-tpm2.out hmac-ossl.out } run_test() { cleanup "no-shut-down" parent_alg=$1 name_alg=$2 tpm2 createprimary -Q -G "$parent_alg" -g "$name_alg" -C o -c parent.ctx # 128 bit AES is 16 bytes if is_alg_supported aes128; then run_aes_import_test parent.ctx aes-128-cfb 16 fi # 256 bit AES is 32 bytes if is_alg_supported aes256; then run_aes_import_test parent.ctx aes-256-cfb 32 fi run_rsa_import_test parent.ctx 1024 run_rsa_import_test parent.ctx 2048 run_ecc_import_test parent.ctx prime256v1 run_keyedhash_seal_import_test parent.ctx run_keyedhash_hmac_import_test parent.ctx } # # Run the tests against: # - RSA2048 with AES CFB 128 and 256 bit parents # - SHA256 object (not parent) name algorithms # parent_algs=("rsa2048:aes128cfb" "rsa2048:aes256cfb" "ecc256:aes128cfb") halgs=`populate_hash_algs 'and alg != "sha1"'` echo "halgs: $halgs" for pa in "${parent_algs[@]}"; do for name in $halgs; do if is_alg_supported $pa; then echo "$pa - $name" run_test "$pa" "$name" fi done; done; # # Test the passin options # tpm2 createprimary -Q -c parent.ctx openssl genrsa -aes128 -passout "pass:mypassword" -out "private.pem" 1024 run_rsa_import_passin_test "parent.ctx" "private.pem" "pass:mypassword" export envvar="mypassword" run_rsa_import_passin_test "parent.ctx" "private.pem" "env:envvar" echo -n "mypassword" > "passfile" run_rsa_import_passin_test "parent.ctx" "private.pem" "file:passfile" exec 42<> passfile run_rsa_import_passin_test "parent.ctx" "private.pem" "fd:42" run_rsa_import_passin_test "parent.ctx" "private.pem" "stdin" "passfile" run_aes_policy_import_test "parent.ctx" exit 0 tpm2-tools-5.2/test/integration/tests/import_tpm.sh000066400000000000000000000107331412464516500226060ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx \ new_parent.prv new_parent.pub new_parent.ctx \ ipolicy.dat dpolicy.dat session.dat \ key.prv key.pub key.ctx \ dup.prv dup.pub dup.seed \ key2.prv key2.pub key2.ctx \ sym_key_in.bin \ dup.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up create_policy() { tpm2 startauthsession -Q -S session.dat tpm2 policycommandcode -Q -S session.dat -L $1 $2 tpm2 flushcontext -Q session.dat rm session.dat } start_session() { tpm2 startauthsession -Q --policy-session -S session.dat tpm2 policycommandcode -Q -S session.dat -L $1 $2 } end_session() { tpm2 flushcontext -Q session.dat rm session.dat } create_load_new_parent() { # Create new parent tpm2 create -Q -C primary.ctx -g sha256 -G rsa -r new_parent.prv \ -u new_parent.pub -a "restricted|sensitivedataorigin|decrypt|userwithauth" # Load new parent key, only the public part tpm2 loadexternal -Q -C o -u new_parent.pub -c new_parent.ctx } load_new_parent() { # Load new parent key, public & private parts tpm2 load -Q -C primary.ctx -r new_parent.prv -u new_parent.pub \ -c new_parent.ctx } create_load_duplicatee() { # Create the key we want to duplicate create_policy dpolicy.dat TPM2_CC_Duplicate if [ -z "$2" ];then tpm2 create -Q -C primary.ctx -g sha256 -G $1 -r key.prv \ -u key.pub -L dpolicy.dat -a "sensitivedataorigin|decrypt|userwithauth" else tpm2 create -Q -C primary.ctx -g sha256 -G $1 -p "$2" -r key.prv \ -u key.pub -L dpolicy.dat -a "sensitivedataorigin|decrypt|userwithauth" fi # Load the key tpm2 load -Q -C primary.ctx -r key.prv -u key.pub -c key.ctx # Extract the public part for import later tpm2 readpublic -Q -c key.ctx -o dup.pub } do_duplication() { start_session dpolicy.dat TPM2_CC_Duplicate if [ "$2" = "aes" ] then tpm2 duplicate -Q -C new_parent.ctx -c key.ctx -G aes -o sym.key \ -p "session:session.dat" -r dup.dup -s dup.seed else tpm2 duplicate -Q -C new_parent.ctx -c key.ctx -G null \ -p "session:session.dat" -r dup.dup -s dup.seed fi end_session } do_import_load() { if [ "$2" = "aes" ] then tpm2 import -Q -C new_parent.ctx -k sym.key -u dup.pub -i dup.dup \ -r dup.prv -s dup.seed else tpm2 import -Q -C new_parent.ctx -u dup.pub -i dup.dup -r dup.prv \ -s dup.seed fi tpm2 load -Q -C new_parent.ctx -r dup.prv -u dup.pub -c dup.ctx } test() { # New parent ... create_load_new_parent # Key to be duplicated create_load_duplicatee $1 # Duplicate the key do_duplication $2 # Remove, we're done with it rm new_parent.ctx # Load the full thing this time load_new_parent # Import & load the duplicate do_import_load $2 } # Part 1 : Duplicate 3 varieties of key (aes, rsa or ecc) # and protect them using sym_alg null or aes, verify they # can be imported & loaded for dup_key_type in aes rsa ecc; do for sym_key_type in aes null; do tpm2 createprimary -Q -C o -g sha256 -G rsa -c primary.ctx test $dup_key_type $sym_key_type cleanup "no-shut-down" done done test_key_usage() { # Part 2 : # Create a rsa key (Kd) # Encrypt a message using Kd # Duplicate Kd # Import & Load Kd # Decrypt the message and verify tpm2 createprimary -Q -C o -g sha256 -G rsa -c primary.ctx # New parent ... create_load_new_parent # Key to be duplicated create_load_duplicatee rsa "$1" # Encrypt a secret message echo "Mary had a little lamb ..." > plain.txt tpm2 rsaencrypt -Q -c key.ctx -o cipher.txt plain.txt # Duplicate the key do_duplication null # Remove, we're done with it rm new_parent.ctx # Load the full thing this time load_new_parent # Import & load the duplicate do_import_load null # Decrypt the secret message using duplicated key if [ -z "$1" ];then tpm2 rsadecrypt -Q -c dup.ctx -o recovered.txt cipher.txt else tpm2 rsadecrypt -Q -p "$1" -c dup.ctx -o recovered.txt cipher.txt fi # Check we got it right ... diff recovered.txt plain.txt # Cleanup rm plain.txt recovered.txt cipher.txt cleanup "no-shut-down" } #Test key with password test_key_usage foo #Test key without password test_key_usage exit 0 tpm2-tools-5.2/test/integration/tests/incrementalselftest.sh000066400000000000000000000037661412464516500244770ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Get the list of remaining algs to be tested temp=$(mktemp) tpm2 incrementalselftest > "${temp}" cat ${temp} alglist="$(yaml_get_kv "${temp}" "remaining" || true)" rm -f "${temp}" # If the list of remaining algs is not empty, we can test # the behaviour of tpm2 incrementalselftest and see # each alg become scheduled and tested. If there are # some leftovers, just print them if [ -n "${alglist}" ]; then for i in ${alglist}; do if ! tpm2 incrementalselftest "${i}" ; then echo "${i} failed to be tested." exit 1 fi done localtmp=$(mktemp) tpm2 incrementalselftest > "${localtmp}" alglist="$(yaml_get_kv "${localtmp}" "remaining" || true)" rm -f "${localtmp}" if [ -n "${alglist}" ]; then echo "Algorithm suite remaning : ${alglist}" else true fi fi # Finally just verify that every algorithm are # effectively being already tested aesmodes="$(populate_algs "details['encrypting'] and details['symmetric']")" hashalgs="$(populate_algs "details['hash'] and not details['method'] \ and not details['signing'] \ and not details['symmetric'] \ and alg is not None")" eccmethods="$(populate_algs "details['signing'] and not details['hash'] \ and \"ec\" in alg")" rsamethods="$(populate_algs "details['signing'] and not details['hash'] \ and \"rsa\" in alg")" # Check testing of AES modes tpm2 incrementalselftest ${aesmodes} | grep -q "complete" # Check testing of Hash algorithms tpm2 incrementalselftest ${hashalgs} | grep -q "complete" # Check testing of ECC methods tpm2 incrementalselftest ${eccmethods} | grep -q "complete" # Check testing of RSA methods tpm2 incrementalselftest ${rsamethods} | grep -q "complete" exit 0 tpm2-tools-5.2/test/integration/tests/load.sh000066400000000000000000000033721412464516500213340ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up alg_primary_obj=sha256 alg_primary_key=rsa alg_create_obj=sha256 alg_create_key=hmac alg_load=sha1 file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_load_key_pub=opu_"$alg_create_obj"_"$alg_create_key" file_load_key_priv=opr_"$alg_create_obj"_"$alg_create_key" file_load_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" file_load_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" file_load_output=load_"$file_load_key_ctx" Handle_parent=0x81010018 Handle_ek_load=0x81010017 cleanup() { rm -f $file_load_key_pub $file_load_key_priv $file_load_key_name \ $file_load_key_ctx tpm2 evictcontrol -Q -Co -c $Handle_parent 2>/dev/null || true if [ $(ina "$@" "keep_ctx") -ne 0 ]; then rm -f $file_primary_key_ctx fi if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT cleanup "no-shut-down" tpm2 clear #####file test tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_create_obj -G $alg_create_key -u $file_load_key_pub \ -r $file_load_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_load_key_pub \ -r $file_load_key_priv -n $file_load_key_name -c $file_load_key_ctx #####handle test cleanup "keep_ctx" "no-shut-down" tpm2 evictcontrol -Q -C o -c $file_primary_key_ctx $Handle_parent tpm2 create -Q -C $Handle_parent -g $alg_create_obj -G $alg_create_key \ -u $file_load_key_pub -r $file_load_key_priv tpm2 load -Q -C $Handle_parent -u $file_load_key_pub -r $file_load_key_priv \ -n $file_load_key_name -c $file_load_key_ctx exit 0 tpm2-tools-5.2/test/integration/tests/loadexternal.sh000066400000000000000000000150531412464516500230760ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=rsa alg_create_obj=sha256 alg_create_key=hmac file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_loadexternal_key_pub=opu_"$alg_create_obj"_"$alg_create_key" file_loadexternal_key_priv=opr_"$alg_create_obj"_"$alg_create_key" file_loadexternal_key_name=name.loadexternal_"$alg_primary_obj"_\ "$alg_primary_key"-"$alg_create_obj"_"$alg_create_key" file_loadexternal_key_ctx=ctx_loadexternal_out_"$alg_primary_obj"_\ "$alg_primary_key"-"$alg_create_obj"_"$alg_create_key" file_loadexternal_output=loadexternal_"$file_loadexternal_key_ctx" Handle_parent=0x81010019 cleanup() { rm -f $file_primary_key_ctx $file_loadexternal_key_pub \ $file_loadexternal_key_priv $file_loadexternal_key_name \ $file_loadexternal_key_ctx $file_loadexternal_output private.pem public.pem \ plain.txt plain.rsa.dec key.ctx public.ecc.pem private.ecc.pem \ data.in.digest data.out.signed ticket.out name.bin stdout.yaml passfile \ private.pem if [ $(ina "$@" "keep_handle") -ne 0 ]; then tpm2 evictcontrol -Q -Co -c $Handle_parent 2>/dev/null || true fi if [ $(ina "$@" "no-shut-down") -ne 0 ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear run_tss_test() { tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_create_obj -G $alg_create_key \ -u $file_loadexternal_key_pub -r $file_loadexternal_key_priv \ -C $file_primary_key_ctx tpm2 loadexternal -Q -C n -u $file_loadexternal_key_pub \ -c $file_loadexternal_key_ctx tpm2 evictcontrol -Q -C o -c $file_primary_key_ctx $Handle_parent # Test with Handle cleanup "keep_handle" "no-shut-down" tpm2 create -Q -C $Handle_parent -g $alg_create_obj -G $alg_create_key \ -u $file_loadexternal_key_pub -r $file_loadexternal_key_priv tpm2 loadexternal -Q -C n -u $file_loadexternal_key_pub \ -c $file_loadexternal_key_ctx # Test with default hierarchy (and handle) cleanup "keep_handle" "no-shut-down" tpm2 create -Q -C $Handle_parent -g $alg_create_obj -G $alg_create_key \ -u $file_loadexternal_key_pub -r $file_loadexternal_key_priv tpm2 loadexternal -Q -u $file_loadexternal_key_pub \ -c $file_loadexternal_key_ctx cleanup "no-shut-down" } # Test loading an OSSL generated private key with a password run_rsa_test() { openssl genrsa -out private.pem $1 openssl rsa -in private.pem -out public.pem -outform PEM -pubout echo "hello world" > plain.txt openssl pkeyutl -encrypt -inkey public.pem -pubin -in plain.txt \ -out plain.rsa.enc tpm2 loadexternal -G rsa -C n -p foo -r private.pem -c key.ctx tpm2 rsadecrypt -c key.ctx -p foo -o plain.rsa.dec plain.rsa.enc diff plain.txt plain.rsa.dec # try encrypting with the public key and decrypting with the private tpm2 loadexternal -G rsa -C n -p foo -u public.pem -c key.ctx tpm2 rsaencrypt -c key.ctx plain.txt -o plain.rsa.enc openssl pkeyutl -decrypt -inkey private.pem -in plain.rsa.enc \ -out plain.rsa.dec diff plain.txt plain.rsa.dec cleanup "no-shut-down" } # # Verify loading an external AES key. # # Paramter 1: The AES keysize to create in bytes. # # Notes: Also tests that name output and YAML output are valid. # run_aes_test() { dd if=/dev/urandom of=sym.key bs=1 count=$(($1 / 8)) 2>/dev/null tpm2 loadexternal -G aes -r sym.key -n name.bin -c key.ctx > stdout.yaml local name1=$(yaml_get_kv "stdout.yaml" "name") local name2="$(xxd -c 256 -p name.bin)" test "$name1" == "$name2" echo "plaintext" > "plain.txt" if is_cmd_supported "EncryptDecrypt"; then tpm2 encryptdecrypt -c key.ctx -o plain.enc plain.txt openssl enc -in plain.enc -out plain.dec.ssl -d -K `xxd -c 256 -p sym.key` \ -iv 0 -aes-$1-cfb diff plain.txt plain.dec.ssl else tpm2 readpublic -c key.ctx >out.pub alg=$(yaml_get_kv out.pub "sym-alg" "value") len=$(yaml_get_kv out.pub "sym-keybits") if [ "$alg$len" != "aes$1" ]; then echo "Algorithm parsed from tpm2 readpublic is '$alg$len' but \ should be 'aes$1'" exit 1 fi rm out.pub fi cleanup "no-shut-down" } run_ecc_test() { # # Test loading an OSSL PEM format ECC key, and verifying a signature # external to the TPM # # # Generate a NIST P256 Private and Public ECC pem file # openssl ecparam -name $1 -genkey -noout -out private.ecc.pem openssl ec -in private.ecc.pem -out public.ecc.pem -pubout # Generate a hash to sign echo "data to sign" > data.in.raw shasum -a 256 data.in.raw | awk '{ print "000000 " $1 }' | xxd -r -c 32 > \ data.in.digest # Load the private key for signing tpm2 loadexternal -Q -G ecc -r private.ecc.pem -c key.ctx # Sign in the TPM and verify with OSSL tpm2 sign -Q -c key.ctx -g sha256 -d -f plain -o data.out.signed \ data.in.digest openssl dgst -verify public.ecc.pem -keyform pem -sha256 -signature \ data.out.signed data.in.raw # Sign with openssl and verify with TPM but only with the public portion of # an object loaded tpm2 loadexternal -Q -G ecc -u public.ecc.pem -c key.ctx openssl dgst -sha256 -sign private.ecc.pem -out data.out.signed data.in.raw tpm2 verifysignature -Q -c key.ctx -g sha256 -m data.in.raw -f ecdsa \ -s data.out.signed cleanup "no-shut-down" } run_rsa_passin_test() { openssl genrsa -aes128 -passout "pass:mypassword" -out "private.pem" 1024 if [ "$2" != "stdin" ]; then cmd="tpm2 loadexternal -Q -G rsa -r $1 -c key.ctx --passin $2" else cmd="tpm2 loadexternal -Q -G rsa -r $1 -c key.ctx --passin $2 < $3" fi; eval $cmd cleanup "no-shut-down" } run_tss_test for len in "1024 2048"; do if is_alg_supported "rsa$len"; then run_rsa_test $len fi done for len in "128 256"; do if is_alg_supported "aes$len"; then run_aes_test $len fi done if is_alg_supported "ecc256"; then run_ecc_test prime256v1 fi # # Test loadexternal passin option # run_rsa_passin_test "private.pem" "pass:mypassword" export envvar="mypassword" run_rsa_passin_test "private.pem" "env:envvar" echo -n "mypassword" > "passfile" run_rsa_passin_test "private.pem" "file:passfile" echo -n "mypassword" > "passfile" exec 42<> passfile run_rsa_passin_test "private.pem" "fd:42" echo -n "mypassword" > "passfile" run_rsa_passin_test "private.pem" "stdin" "passfile" exit 0 tpm2-tools-5.2/test/integration/tests/makecredential.sh000066400000000000000000000026671412464516500233730ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh handle_ek=0x81010007 ak_ctx=ak.ctx ek_alg=rsa ak_alg=rsa digestAlg=sha256 signAlg=rsassa file_input_data=secret.data output_ek_pub=ek_pub.out output_ak_pub=ak_pub.out output_ak_pub_name=ak_name_pub.out output_mkcredential=mkcredential.out cleanup() { rm -f $output_ek_pub $output_ak_pub $output_ak_pub_name \ $output_mkcredential $file_input_data output_ak grep.txt $ak_ctx tpm2 evictcontrol -Q -Co -c $handle_ek 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 createek -Q -c $handle_ek -G $ek_alg -u $output_ek_pub tpm2 createak -Q -C $handle_ek -c $ak_ctx -G $ak_alg -g $digestAlg -s $signAlg \ -u $output_ak_pub -n $output_ak_pub_name # Use -c in xxd so there is no line wrapping file_size=`ls -l $output_ak_pub_name | awk {'print $5'}` Loadkeyname=`cat $output_ak_pub_name | xxd -p -c $file_size` tpm2 makecredential -Q -u $output_ek_pub -s $file_input_data -n $Loadkeyname \ -o $output_mkcredential # use no tpm backend tpm2 makecredential -T none -Q -u $output_ek_pub -s $file_input_data \ -n $Loadkeyname -o $output_mkcredential # use no tpm backend and EK in PEM format tpm2 readpublic -c $handle_ek -o ek.pem -f pem -Q tpm2 makecredential -T none -Q -u ek.pem -G rsa -s $file_input_data \ -n $Loadkeyname -o $output_mkcredential exit 0 tpm2-tools-5.2/test/integration/tests/nv.sh000066400000000000000000000206771412464516500210470ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause if [ "`uname`" == "FreeBSD" ]; then exit 77 fi source helpers.sh nv_test_index=0x1500018 large_file_name="nv.test_large_w" large_file_read_name="nv.test_large_r" pcr_specification=sha256:0,1,2,3+sha1:0,1,2,3 file_pcr_value=pcr.bin file_policy=policy.data cleanup() { tpm2 nvundefine -Q $nv_test_index -C o 2>/dev/null || true tpm2 nvundefine -Q 0x1500016 -C o 2>/dev/null || true tpm2 nvundefine -Q 0x1500015 -C o -P owner 2>/dev/null || true rm -f policy.bin test.bin nv.test_w $large_file_name $large_file_read_name \ nv.readlock foo.dat cmp.dat $file_pcr_value $file_policy nv.out cap.out yaml.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear #Test nvdefine with no options tpm2 nvdefine > yaml.out tpm2 nvundefine $(yaml_get_kv yaml.out "nv-index") #Test default values for the hierarchy "-a" parameter tpm2 nvdefine -Q $nv_test_index -s 32 -a "ownerread|policywrite|ownerwrite" tpm2 nvundefine -Q $nv_test_index #Test writing and reading tpm2 nvdefine -Q $nv_test_index -C o -s 32 \ -a "ownerread|policywrite|ownerwrite" echo "please123abc" > nv.test_w tpm2 nvwrite -Q $nv_test_index -C o -i nv.test_w tpm2 nvread -Q $nv_test_index -C o -s 32 -o 0 tpm2 nvreadpublic > nv.out yaml_get_kv nv.out "$nv_test_index" > /dev/null yaml_get_kv nv.out "$nv_test_index" "name" > /dev/null # Test writing to and reading from an offset by: # 1. writing "foo" into the nv file at an offset # 2. writing to the same offset in the nv index # 3. reading back the index # 4. comparing the result. echo -n "foo" > foo.dat dd if=foo.dat of=nv.test_w bs=1 seek=4 conv=notrunc 2>/dev/null # Test a pipe input cat foo.dat | tpm2 nvwrite -Q $nv_test_index -C o --offset 4 -i - tpm2 nvread $nv_test_index -C o -s 13 > cmp.dat cmp nv.test_w cmp.dat # Writing at an offset and data size too big shouldn't result in a change # to the index value. trap - ERR tpm2 nvwrite -Q $nv_test_index -C o -o 30 -i foo.dat 2>/dev/null if [ $? -eq 0 ]; then echo "Writing past the public size shouldn't work!" exit 1 fi trap onerror ERR tpm2 nvread $nv_test_index -C o -s 13 > cmp.dat cmp nv.test_w cmp.dat tpm2 nvundefine $nv_test_index -C o tpm2 pcrread -Q -o $file_pcr_value $pcr_specification tpm2 createpolicy -Q --policy-pcr -l $pcr_specification -f $file_pcr_value \ -L $file_policy tpm2 nvdefine -Q 0x1500016 -C o -s 32 -L $file_policy \ -a "policyread|policywrite" # Write with index authorization for now, since tpm2 nvwrite does not support # pcr policy. echo -n "policy locked" | tpm2 nvwrite -Q 0x1500016 -C 0x1500016 \ -P pcr:$pcr_specification=$file_pcr_value -i - str=`tpm2 nvread 0x1500016 -C 0x1500016 \ -P pcr:$pcr_specification=$file_pcr_value -s 13` test "policy locked" == "$str" # this should fail because authread is not allowed trap - ERR tpm2 nvread 0x1500016 -C 0x1500016 -P "index" 2>/dev/null trap onerror ERR tpm2 nvundefine -Q 0x1500016 -C o # # Test large writes # tpm2 getcap properties-fixed > cap.out large_file_size=`yaml_get_kv cap.out "TPM2_PT_NV_INDEX_MAX" "raw"` nv_test_index=0x1000000 # Create an nv space with attributes 1010 = TPMA_NV_PPWRITE and # TPMA_NV_AUTHWRITE tpm2 nvdefine -Q $nv_test_index -C o -s $large_file_size -a 0x2000A base64 /dev/urandom | head -c $(($large_file_size)) > $large_file_name # Test file input redirection tpm2 nvwrite -Q $nv_test_index -C o -i -< $large_file_name tpm2 nvread $nv_test_index -C o > $large_file_read_name cmp -s $large_file_read_name $large_file_name # test per-index readpublic tpm2 nvreadpublic "$nv_test_index" > nv.out yaml_get_kv nv.out "$nv_test_index" > /dev/null tpm2 nvundefine -Q $nv_test_index -C o # # Test NV access locked # tpm2 nvdefine -Q $nv_test_index -C o -s 32 \ -a "ownerread|policywrite|ownerwrite|read_stclear|writedefine" echo "foobar" > nv.readlock tpm2 nvwrite -Q $nv_test_index -C o -i nv.readlock tpm2 nvread -Q $nv_test_index -C o -s 6 -o 0 tpm2 nvreadlock -Q $nv_test_index -C o # Reset ERR signal handler to test for expected nvread error trap - ERR tpm2 nvread -Q $nv_test_index -C o -s 6 -o 0 2> /dev/null if [ $? != 1 ];then echo "nvread didn't fail!" exit 1 fi trap onerror ERR # Test that write lock works tpm2 nvwritelock -C o $nv_test_index trap - ERR tpm2 nvwrite $nv_test_index -C o -i nv.readlock if [ $? != 1 ];then echo "nvwrite didn't fail!" exit 1 fi tpm2 nvundefine -C o $nv_test_index trap onerror ERR # # Test that owner and index passwords work by # 1. Setting up the owner password # 2. Defining an nv index that can be satisfied by an: # a. Owner authorization # b. Index authorization # 3. Using index and owner based auth during write/read operations # 4. Testing that auth is needed or a failure occurs. # tpm2 changeauth -c o owner tpm2 nvdefine 0x1500015 -C o -s 32 \ -a "policyread|policywrite|authread|authwrite|ownerwrite|ownerread" \ -p "index" -P "owner" # Use index password write/read, implicit -a tpm2 nvwrite -Q 0x1500015 -P "index" -i nv.test_w tpm2 nvread -Q 0x1500015 -P "index" # Use index password write/read, explicit -a tpm2 nvwrite -Q 0x1500015 -C 0x1500015 -P "index" -i nv.test_w tpm2 nvread -Q 0x1500015 -C 0x1500015 -P "index" # use owner password tpm2 nvwrite -Q 0x1500015 -C o -P "owner" -i nv.test_w tpm2 nvread -Q 0x1500015 -C o -P "owner" # Check a bad password fails trap - ERR tpm2 nvwrite -Q 0x1500015 -C 0x1500015 -P "wrong" -i nv.test_w 2>/dev/null if [ $? -eq 0 ];then echo "nvwrite with bad password should fail!" exit 1 fi # Check using authorisation with tpm2 nvundefine trap onerror ERR tpm2 nvundefine 0x1500015 -C o -P "owner" # Check nv index can be specified simply as an offset tpm2 nvdefine -Q -C o -s 32 -a "ownerread|ownerwrite" 1 -P "owner" tpm2 nvundefine 0x01000001 -C o -P "owner" # Test setbits tpm2 nvdefine -C o -P "owner" -a "nt=bits|ownerread|policywrite|ownerwrite|writedefine" $nv_test_index tpm2 nvsetbits -C o -P "owner" -i 0xbadc0de $nv_test_index check=$(tpm2 nvread -C o -P "owner" $nv_test_index | xxd -p | sed s/'^0*'/0x/) if [ "$check" != "0xbadc0de" ]; then echo "Expected setbits read value of 0xbadc0de, got \"$check\"" exit 1 fi # Test global writelock if is_cmd_supported "NV_GlobalWriteLock"; then tpm2 nvdefine -C o -P "owner" -s 32 -a "ownerread|ownerwrite|globallock" 42 tpm2 nvdefine -C o -P "owner" -s 32 -a "ownerread|ownerwrite|globallock" 43 tpm2 nvdefine -C o -P "owner" -s 32 -a "ownerread|ownerwrite|globallock" 44 echo foo | tpm2 nvwrite -C o -P "owner" -i- 42 echo foo | tpm2 nvwrite -C o -P "owner" -i- 43 echo foo | tpm2 nvwrite -C o -P "owner" -i- 44 tpm2 nvwritelock -Co -P owner --global # These writes should fail now that its in a writelocked state trap - ERR echo foo | tpm2 nvwrite -C o -P "owner" -i- 42 if [ $? -eq 0 ]; then echo "Expected tpm2 nvwrite to fail after globalwritelock of index 42" exit 1 fi echo foo | tpm2 nvwrite -C o -P "owner" -i- 43 if [ $? -eq 0 ]; then echo "Expected tpm2 nvwrite to fail after globalwritelock of index 43" exit 1 fi echo foo | tpm2 nvwrite -C o -P "owner" -i- 44 if [ $? -eq 0 ]; then echo "Expected tpm2 nvwrite to fail after globalwritelock of index 44" exit 1 fi fi trap onerror ERR tpm2 nvundefine -C o -P "owner" $nv_test_index # Test extend tpm2 nvdefine -C o -P "owner" -a "nt=extend|ownerread|policywrite|ownerwrite" $nv_test_index echo "foo" | tpm2 nvextend -C o -P "owner" -i- $nv_test_index check=$(tpm2 nvread -C o -P "owner" $nv_test_index | xxd -p -c 64 | sed s/'^0*'//) expected="1c8457de84bb43c18d5e1d75c43e393bdaa7bca8d25967eedd580c912db65e3e" if [ "$check" != "$expected" ]; then echo "Expected setbits read value of \"$expected\", got \"$check\"" exit 1 fi # Test nvextend and nvdefine with aux sessions tpm2 clear tpm2 createprimary -C o -c prim.ctx tpm2 startauthsession -S enc_session.ctx --hmac-session -c prim.ctx tpm2 changeauth -c o owner tpm2 nvdefine -C o -P owner -a "nt=extend|ownerread|policywrite|ownerwrite" \ $nv_test_index -p nvindexauth -S enc_session.ctx echo "foo" | tpm2 nvextend -C o -P owner -i- $nv_test_index -S enc_session.ctx tpm2 flushcontext enc_session.ctx rm enc_session.ctx rm prim.ctx check=$(tpm2 nvread -C o -P owner $nv_test_index | xxd -p -c 64 | sed s/'^0*'//) expected="1c8457de84bb43c18d5e1d75c43e393bdaa7bca8d25967eedd580c912db65e3e" if [ "$check" != "$expected" ]; then echo "Expected setbits read value of \"$expected\", got \"$check\"" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/nvcertify.sh000066400000000000000000000024551412464516500224270ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f primary.ctx signing_key.pub signing_key.priv signature.bin attestation.bin \ sslpub.pem signing_key.ctx qual.dat if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear -Q tpm2 createprimary -C o -c primary.ctx -Q tpm2 create -G rsa -u signing_key.pub -r signing_key.priv -C primary.ctx \ -c signing_key.ctx -Q tpm2 readpublic -c signing_key.ctx -f pem -o sslpub.pem -Q tpm2 nvdefine -s 32 -a "authread|authwrite" 1 dd if=/dev/urandom bs=1 count=32 status=none| tpm2 nvwrite 1 -i- tpm2 nvcertify -C signing_key.ctx -g sha256 -f plain -s rsassa \ -o signature.bin --attestation attestation.bin --size 32 1 openssl dgst -verify sslpub.pem -keyform pem -sha256 -signature signature.bin \ attestation.bin # # Test with qualifier data # dd if=/dev/urandom of=qual.dat bs=1 count=32 tpm2 nvcertify -C signing_key.ctx -g sha256 -f plain -s rsassa \ -o signature.bin --attestation attestation.bin --size 32 -q qual.dat 1 openssl dgst -verify sslpub.pem -keyform pem -sha256 -signature signature.bin \ attestation.bin # # Test if qualifier data was present in the attestation # xxd -p attestation.bin | tr -d '\n' | grep `xxd -p qual.dat | tr -d '\n'` exit 0 tpm2-tools-5.2/test/integration/tests/nvinc.sh000066400000000000000000000074341412464516500215350ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #;**********************************************************************; source helpers.sh nv_test_index=0x1500018 pcr_specification=sha256:0,1,2,3+sha1:0,1,2,3 file_pcr_value=pcr.bin file_policy=policy.data cleanup() { tpm2 nvundefine -Q $nv_test_index -C o 2>/dev/null || true tpm2 nvundefine -Q 0x1500016 -C o 2>/dev/null || true tpm2 nvundefine -Q 0x1500015 -C o -P owner 2>/dev/null || true rm -f policy.bin test.bin nv.readlock foo.dat $file_pcr_value $file_policy \ nv.out cap.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear tpm2 nvdefine -Q $nv_test_index -C o -s 8 \ -a "ownerread|policywrite|ownerwrite|nt=1" tpm2 nvincrement -Q $nv_test_index -C o a=0x$(tpm2 nvread $nv_test_index -C o -s 8 | xxd -p) tpm2 nvreadpublic > nv.out yaml_get_kv nv.out "$nv_test_index" > /dev/null # Test writing to and reading from an offset by: # 1. incrementing the nv counter # 2. reading back the index # 3. comparing the result. tpm2 nvincrement -Q $nv_test_index -C o b=0x$(tpm2 nvread $nv_test_index -C o -s 8 | xxd -p) if [ $(($a+1)) -ne $(($b)) ]; then echo "Failed to increment: $(($a)) -> $(($b))." exit 1 fi tpm2 nvundefine $nv_test_index -C o tpm2 pcrread -Q -o $file_pcr_value $pcr_specification tpm2 createpolicy -Q --policy-pcr -l $pcr_specification \ -f $file_pcr_value -L $file_policy tpm2 nvdefine -Q 0x1500016 -C o -s 8 -L $file_policy \ -a "policyread|policywrite|nt=1" # Increment with index authorization for now, since tpm2 nvincrement does not # support pcr policy. # Counter is initialised to highest value previously seen (in this case 2) then # incremented tpm2 nvincrement -Q 0x1500016 -C 0x1500016 \ -P pcr:$pcr_specification=$file_pcr_value c=0x$(tpm2 nvread 0x1500016 -C 0x1500016 -P pcr:$pcr_specification=$file_pcr_value -s 8 | xxd -p) if [ $(($b+1)) -ne $(($c)) ]; then echo "Failed to increment: $(($b)) -> $(($c))." exit 1 fi # this should fail because authread is not allowed trap - ERR tpm2 nvread 0x1500016 -C 0x1500016 -P "index" 2>/dev/null trap onerror ERR tpm2 nvundefine -Q 0x1500016 -C o # # Test NV access locked # tpm2 nvdefine -Q $nv_test_index -C o -s 8 \ -a "ownerread|policywrite|ownerwrite|read_stclear|nt=1" tpm2 nvincrement -Q $nv_test_index -C o tpm2 nvread -Q $nv_test_index -C o -s 8 tpm2 nvreadlock -Q $nv_test_index -C o # Reset ERR signal handler to test for expected nvread error trap - ERR tpm2 nvread -Q $nv_test_index -C o -s 8 2> /dev/null if [ $? != 1 ];then echo "nvread didn't fail!" exit 1 fi # # Test that owner and index passwords work by # 1. Setting up the owner password # 2. Defining an nv index that can be satisfied by an: # a. Owner authorization # b. Index authorization # 3. Using index and owner based auth during write/read operations # 4. Testing that auth is needed or a failure occurs. # trap onerror ERR tpm2 changeauth -c o owner tpm2 nvdefine 0x1500015 -C o -s 8 \ -a "policyread|policywrite|authread|authwrite|ownerwrite|ownerread|nt=1" \ -p "index" -P "owner" # Use index password write/read, implicit -C tpm2 nvincrement -Q 0x1500015 -P "index" tpm2 nvread -Q 0x1500015 -P "index" # Use index password write/read, explicit -C tpm2 nvincrement -Q 0x1500015 -C 0x1500015 -P "index" tpm2 nvread -Q 0x1500015 -C 0x1500015 -P "index" # use owner password tpm2 nvincrement -Q 0x1500015 -C o -P "owner" tpm2 nvread -Q 0x1500015 -C o -P "owner" # Check a bad password fails trap - ERR tpm2 nvincrement -Q 0x1500015 -C 0x1500015 -P "wrong" 2>/dev/null if [ $? -eq 0 ];then echo "nvincrement with bad password should fail!" exit 1 fi # Check using authorisation with tpm2 nvundefine trap onerror ERR tpm2 nvundefine 0x1500015 -C o -P "owner" exit 0 tpm2-tools-5.2/test/integration/tests/output_formats.sh000066400000000000000000000064261412464516500235130ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh # Purpose of this test is to cover the additional code paths that come into # play when non-default output formats for public keys or signatures are used # in the various tools. # # The test covers all available output formats, makes sure the tools # successfully run in these cases and checks the output files by feeding them # to OpenSSL as appropriate. alg_ek=rsa file_pubek_base=ek_${alg_ek} file_pubek_orig=${file_pubek_base}.tss.orig handle_ek=0x81010014 alg_ak=rsa file_pubak_name="ak.${alg_ak}.name" file_pubak_tss="ak.${alg_ak}.tss" file_pubak_pem="ak.${alg_ak}.pem" handle_ak=0x81010016 handle_ak_file=ak.handle ak_ctx=ak.ctx file_hash_input="hash.in" file_hash_ticket=hash.ticket file_hash_result=hash.result file_sig_base=hash.sig alg_hash=sha256 file_quote_msg=quote.msg file_quote_sig_base=quote.sig cleanup() { rm -f "$file_pubek_base".* rm -f "$file_pubak_tss" "$file_pubak_name" "$file_pubak_pem" rm -f "$file_hash_ticket" "$file_hash_result" "$file_sig_base".* rm -f "$file_quote_msg" "$file_quote_sig_base".* $file_hash_input rm -f primary.ctx ecc.ctx ecc.pub ecc.priv ecc.fmt.pub $ak_ctx # Evict persistent handles, we want them to always succeed and never trip # the onerror trap. for handle in $handle_ek $handle_ak; do tpm2 evictcontrol -Q -C o -c $handle 2>/dev/null || true done shut_down } trap cleanup EXIT start_up head -c 4096 /dev/urandom > $file_hash_input tpm2 createek -Q -G $alg_ek -u "$file_pubek_orig" -c $handle_ek for fmt in tss pem der; do this_key="${file_pubek_base}.${fmt}" tpm2 readpublic -Q -c $handle_ek -f "$fmt" -o "$this_key" if [ "$fmt" = tss ]; then diff "$file_pubek_orig" "$this_key" > /dev/null else openssl rsa -pubin -inform "$fmt" -text -in "$this_key" &> /dev/null fi done tpm2 createak -Q -G $alg_ak -C $handle_ek -c $ak_ctx -u "$file_pubak_tss" \ -n "$file_pubak_name" echo "tpm2 evictcontrol -Q -c $ak_ctx -o $handle_ak_file" $handle_ak tpm2 evictcontrol -Q -c $ak_ctx -o $handle_ak_file $handle_ak tpm2 readpublic -Q -c $handle_ak_file -f "pem" -o "$file_pubak_pem" tpm2 hash -Q -C e -g $alg_hash -t "$file_hash_ticket" -o "$file_hash_result" \ "$file_hash_input" for fmt in tss plain; do this_sig="${file_sig_base}.${fmt}" tpm2 sign -Q -c $handle_ak -g $alg_hash -f $fmt -o "${this_sig}" \ -t "${file_hash_ticket}" "${file_hash_input}" if [ "$fmt" = plain ]; then openssl dgst -verify "$file_pubak_pem" -keyform pem -${alg_hash} \ -signature "$this_sig" "$file_hash_input" > /dev/null fi done for fmt in tss plain; do this_sig="${file_quote_sig_base}.${fmt}" tpm2 quote -Q -c $handle_ak -l "$alg_hash":0 -f $fmt -m "$file_quote_msg" \ -s "$this_sig" if [ "$fmt" = plain ]; then openssl dgst -verify "$file_pubak_pem" -keyform pem -${alg_hash} \ -signature "$this_sig" "$file_quote_msg" > /dev/null fi done # # Test ECC keys # tpm2 createprimary -c primary.ctx tpm2 create -Q -C primary.ctx -G ecc -u ecc.pub -r ecc.priv tpm2 load -C primary.ctx -u ecc.pub -r ecc.priv -c ecc.ctx for fmt in pem der; do tpm2 readpublic -Q -c ecc.ctx -f "$fmt" -o ecc.fmt.pub openssl ec -pubin -inform "$fmt" -text -in ecc.fmt.pub &> /dev/null done exit 0 tpm2-tools-5.2/test/integration/tests/pcrallocate.sh000066400000000000000000000013611412464516500227020ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f pcrs.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Store the old banks because e.g. some TPM-simuators don't support SHA512 OLDBANKS=$(tpm2 getcap pcrs | grep bank | sed 's/.*bank\: \(.*\)/+\1:all/' | \ tr -d "\n") echo "OLDBANKS: $OLDBANKS" tpm2 pcrallocate -P "" sha1:7,8,9,10,16,17,18,19+sha256:all \ | tee out.yml yaml_verify out.yml tpm2 pcrallocate sha1:all+sha256:all | tee out.yml yaml_verify out.yml tpm2 pcrallocate ${OLDBANKS:1} #Note: We cannot check if the allocations were performed by the TPM, since they # will only take effect once the TPM reboots. exit 0 tpm2-tools-5.2/test/integration/tests/pcrevent.sh000066400000000000000000000033371412464516500222440ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #this script is for hash case testing source helpers.sh hash_out_file=hash.out hash_in_file=hash.in yaml_out_file=pcr_list.yaml cleanup() { rm -f $hash_in_file $hash_out_file $yaml_out_file shut_down } trap cleanup EXIT start_up echo "T0naX0u123abc" > $hash_in_file # Run FILE and stdin as FILE tpm2 pcrevent -Q $hash_in_file tpm2 pcrevent -Q < $hash_in_file # Test that fifo stdin works cat $hash_in_file | tpm2 pcrevent > $hash_out_file yaml_verify $hash_out_file # Verify output as expected. while IFS='' read -r l || [[ -n "$l" ]]; do alg=`echo -n $l | cut -d\: -f 1-1` if ! which "$alg"sum >/dev/null 2>&1; then echo "Ignore checking $alg algorithm due to unavailable \"${alg}sum\" program" continue fi hash=`echo -n $l | awk {'print $2'}` check=`"$alg"sum $hash_in_file | cut -d' ' -f 1-1` if [ "$check" != "$hash" ]; then echo "Hash check failed for alg \"$alg\", got \"$hash\", expected \"$check\"" exit 1 fi done < $hash_out_file tpm2 pcrread sha1:9 > $yaml_out_file old_pcr_value=`yaml_get_kv $yaml_out_file "sha1" "9"` # Verify that extend works, and test large files dd if=/dev/urandom of=$hash_in_file count=1 bs=2093 2> /dev/null tpm2 pcrevent -Q 9 $hash_in_file tpm2 pcrread sha1:9 > $yaml_out_file new_pcr_value=`yaml_get_kv $yaml_out_file "sha1" "9"` if [ "$new_pcr_value" == "$old_pcr_value" ]; then echo "Expected PCR value to change after pcrevent with index 9." echo "Got the same hash as before: "$new_pcr_value"". exit 1; fi # verify that specifying -P without -i fails trap - ERR cmd="tpm2 pcrevent -Q -P foo $hash_in_file 2> /dev/null" eval "$cmd" if [ $? -eq 0 ]; then echo "Expected $cmd to fail, passed." exit 1; fi exit 0 tpm2-tools-5.2/test/integration/tests/pcrextend.sh000066400000000000000000000025561412464516500224140ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up declare -A alg_hashes=( ["sha1"]="f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" ["sha256"]="6ea40aa7267bb71251c1de1c3605a3df759b86b22fa9f62aa298d4197cd88a38" ["sha384"]="ecf669bad80a9b2b267d8671bd7d012d92e8cd30fd28d88dcdbcc2ddffbb995c7f226011ac24ae92dcfb493e0a5ecf89" ["sha512"]="18b7381f36cdf5dd7c0b64835e0bf5041a52a38e3c3f4cbabcc4099d52590bf9916808138de511fb172cb64fcc11601f07d114f03e95e3d5ceacb330ce0f856a" ["sm3_256"]="2b14a1fc49869413b0beb707069cffc0c6b0a51f3fedb9ce072c80709652b3ae" ) digests="" # test a single algorithm based on what is supported for alg in `tpm2 getcap pcrs | grep sha |awk {'print $2'} | awk -F: {'print $1'}`; do hash=${alg_hashes[$alg]} if [ ! -z $digests ]; then digests="$digests," fi digests="$digests$alg=$hash" tpm2 pcrextend 9:$alg=$hash done; # # To keep things simple, compound specifications are just done with # the supported sha1 algorithms to guarantee the command to succeed. # tpm2 pcrextend 8:$digests # Extend a PCR for all supported banks like in the previous test but # try extending two PCR in the same command. tpm2 pcrextend 8:$digests 9:$digests # Over-length hash should fail if tpm2 pcrextend 8:$digests,sha1=${alg_hashes["sha256"]}; then echo "tpm2 pcrextend with over-length hash didn't fail!" exit 1 else true fi exit 0 tpm2-tools-5.2/test/integration/tests/pcrlist.sh000066400000000000000000000006011412464516500220650ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f pcrs.out if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 pcrread > pcrs.out yaml_verify pcrs.out tpm2 pcrread -Q 0x04 tpm2 pcrread -Q -o pcrs.out 0x04:17,18,19+sha256:0,17,18,19 test -e pcrs.out tpm2 pcrread -Q exit 0 tpm2-tools-5.2/test/integration/tests/pcrreset.sh000066400000000000000000000007161412464516500222430ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Reset a resettable PCR tpm2 pcrreset 23 # Reset more than one resettable PCR tpm2 pcrreset 16 23 trap - ERR # Get PCR_Reset bad locality error tpm2 pcrreset 0 if [ $? -eq 0 ]; then echo "Expected PCR reset of 0 to induce bad locality error" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/pcrs_format.sh000066400000000000000000000035611412464516500227340ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause # shellcheck disable=SC1091 source helpers.sh cleanup() { rm -f ek.ctx ak.ctx nonce.bin \ quote.pcr quote.pcr.serialized quote.pcr.values \ pcr.read, pcr.read.serialized, pcr.read.values [[ "$1" = "no-shut-down" ]] || shut_down } fail() { echo "$*" > /dev/stderr exit 1 } trap cleanup EXIT start_up cleanup "no-shut-down" # Generate artifacts necessary to make a quote tpm2 createek -G ecc -c ek.ctx tpm2 createak -C ek.ctx -c ak.ctx -G ecc -g sha256 -s ecdsa tpm2 getrandom -o nonce.bin 20 readonly pcrs_selection="sha1:15,16,22+sha256:15,16,22" tpm2 quote -c ak.ctx -l $pcrs_selection -q nonce.bin -m /dev/null -s /dev/null \ -g sha256 -o quote.pcr tpm2 quote -c ak.ctx -l $pcrs_selection -q nonce.bin -m /dev/null -s /dev/null \ -g sha256 -o quote.pcr.serialized -F serialized tpm2 quote -c ak.ctx -l $pcrs_selection -q nonce.bin -m /dev/null -s /dev/null \ -g sha256 -o quote.pcr.values -F values tpm2 pcrread $pcrs_selection -o pcr.read tpm2 pcrread $pcrs_selection -o pcr.read.serialized -F serialized tpm2 pcrread $pcrs_selection -o pcr.read.values -F values diff quote.pcr quote.pcr.serialized >& /dev/null || fail "default pcrs output format of tpm2 quote is expected to be 'serialized'" diff quote.pcr.serialized quote.pcr.values >& /dev/null && fail "pcrs output in 'serialized' format must be different from that" \ "in 'values' format for tpm2 quote" diff quote.pcr.serialized pcr.read.serialized >& /dev/null || fail "pcrs output in 'serialized' format of tpm2 quote and tpm2 pcrread" \ "must be identical" diff quote.pcr.values pcr.read.values >& /dev/null || fail "pcrs output in 'values' format of tpm2 quote and tpm2 pcrread" \ "must be identical" diff pcr.read pcr.read.values >& /dev/null || fail "default pcrs output format of tpm2 pcrread is expected to be 'values'" exit 0 tpm2-tools-5.2/test/integration/tests/print.sh000066400000000000000000000040751412464516500215520ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh ak_ctx=ak.ctx ek_handle=0x81010017 ak_name_file=ak.name ak_pubkey_file=ak.pub quote_file=quote.bin print_file=quote.yaml cleanup() { rm -f $ak_name_file $ak_pubkey_file \ $quote_file $print_file $ak_ctx \ tpmt_public.ak if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear # Create signing key tpm2 createek -Q -G rsa -c $ek_handle tpm2 createak -Q -G rsa -g sha256 -s rsassa -C $ek_handle -c $ak_ctx\ -u $ak_pubkey_file -n $ak_name_file tpm2 readpublic -c $ak_ctx -f tpmt -o tpmt_public.ak tpm2 print -t TPM2B_PUBLIC $ak_pubkey_file > $print_file yaml_verify $print_file tpm2 print -t TPMT_PUBLIC tpmt_public.ak > $print_file yaml_verify $print_file tpm2 print -t TPMT_PUBLIC -f pem tpmt_public.ak > $print_file openssl rsa -noout -text -inform PEM -in $print_file -pubin # Take PCR quote tpm2 quote -Q -c $ak_ctx -l "sha256:0,2,4,9,10,11,12,17" -q "0f8beb45ac" \ -m $quote_file # Print TPM's quote file tpm2 print -t TPMS_ATTEST $quote_file > $print_file # Check printed yaml python << pyscript from __future__ import print_function import sys import re import yaml with open("$print_file") as fd: yaml = yaml.safe_load(fd) assert(yaml["magic"] == "ff544347") assert(yaml["type"] == 8018) assert(yaml["extraData"] == "0f8beb45ac") quote = yaml["attested"]["quote"] # there should be only one pcr selection assert(quote["pcrSelect"]["count"] == 1) pcr_select = quote["pcrSelect"]["pcrSelections"][0] # pcr selection should match above options assert(pcr_select["hash"] == "11 (sha256)") assert(pcr_select["sizeofSelect"] == 3) assert(pcr_select["pcrSelect"] == "151e02") # pcrDigest should be lowercase hex encoded sha256sum per above options assert(re.match('^[0-9a-f]{64}$', quote["pcrDigest"])) print("OK") pyscript # negative testing trap - ERR tpm2 print $quote_file if [ $? -eq 0 ]; then echo "Expected tpm2 print without -t to fail" exit 1 fi exit 0 tpm2-tools-5.2/test/integration/tests/quote.sh000066400000000000000000000062601412464516500215510ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=rsa alg_create_obj=0x000B alg_create_key=hmac alg_quote=0x0004 alg_quote1=0x000b file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_quote_key_pub=opu_"$alg_create_obj"_"$alg_create_key" file_quote_key_priv=opr_"$alg_create_obj"_"$alg_create_key" file_quote_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" file_quote_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" Handle_ak_quote=0x81010016 Handle_ek_quote=0x81010017 Handle_ak_quote2=0x81010018 ak2_ctx=ak2.ctx out=out.yaml toss_out=junk.out cleanup() { rm -f $file_primary_key_ctx $file_quote_key_pub $file_quote_key_priv \ $file_quote_key_name $file_quote_key_ ak.pub2 ak.name_2 \ $out $toss_out $ak2_ctx ek.ctx ak.ctx nonce.bin quote.bin quote.sig quote.pcr tpm2 evictcontrol -Q -Co -c $Handle_ek_quote 2>/dev/null || true tpm2 evictcontrol -Q -Co -c $Handle_ak_quote 2>/dev/null || true tpm2 evictcontrol -Q -Co -c $Handle_ak_quote2 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up tpm2 getcap properties-fixed | tr -dc '[[:print:]]\r\n' > $out maxdigest=$(yaml_get_kv $out "TPM2_PT_MAX_DIGEST" "raw") if ! [[ "$maxdigest" =~ ^(0x)*[0-9]+$ ]] ; then echo "error: not a number, got: \"$maxdigest\"" >&2 exit 1 fi nonce=12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde12345abcde nonce=${nonce:0:2*$maxdigest} cleanup "no-shut-down" tpm2 clear tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_create_obj -G $alg_create_key -u $file_quote_key_pub \ -r $file_quote_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_quote_key_pub \ -r $file_quote_key_priv -n $file_quote_key_name -c $file_quote_key_ctx tpm2 quote -c $file_quote_key_ctx -l $alg_quote:16,17,18 -q $nonce \ -m $toss_out -s $toss_out -o $toss_out -g $alg_primary_obj > $out yaml_verify $out tpm2 quote -Q -c $file_quote_key_ctx \ -l $alg_quote:16,17,18+$alg_quote1:16,17,18 -q $nonce -m $toss_out \ -s $toss_out -o $toss_out -g $alg_primary_obj #####handle testing tpm2 evictcontrol -Q -C o -c $file_quote_key_ctx $Handle_ak_quote tpm2 quote -Q -c $Handle_ak_quote -l $alg_quote:16,17,18 -q $nonce \ -m $toss_out -s $toss_out -o $toss_out -g $alg_primary_obj tpm2 quote -Q -c $Handle_ak_quote -l $alg_quote:16,17,18+$alg_quote1:16,17,18 \ -q $nonce -m $toss_out -s $toss_out -o $toss_out -g $alg_primary_obj #####AK tpm2 createek -Q -c $Handle_ek_quote -G 0x01 tpm2 createak -Q -C $Handle_ek_quote -c $ak2_ctx -u ak.pub2 -n ak.name_2 tpm2 evictcontrol -Q -C o -c $ak2_ctx $Handle_ak_quote2 tpm2 quote -Q -c $Handle_ak_quote -l $alg_quote:16,17,18 -q $nonce \ -m $toss_out -s $toss_out -o $toss_out -g $alg_primary_obj # ECC Test tpm2 createek -G ecc -c ek.ctx tpm2 createak -C ek.ctx -c ak.ctx -G ecc -g sha256 -s ecdsa tpm2 getrandom -o nonce.bin 20 tpm2 quote -c ak.ctx -l sha256:15,16,22 -q nonce.bin -m quote.bin -s quote.sig -o quote.pcr -g sha256 exit 0 tpm2-tools-5.2/test/integration/tests/rc_decode.sh000066400000000000000000000045221412464516500223220ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh # We don't need a TPM for this test, so unset the EXIT handler. trap - EXIT # Since this only tests rc_decode tool it on FreeBSD if [ "$OS" == "FreeBSD" ]; then exit 0 fi # # codes was generated from the TPM2_RC constants in: # https://github.com/tpm2-software/tpm2-tss/blob/master/include/sapi/tss2_tpm2 types.h#L68 # Some of these may not be used correctly, which is OK, as tpm2 rc_decode never # fails and should attempt to decode it or print some unknown status. This gives # us coverage for both known and unknown/malformed inputs. # # Details on error code encoding can be found at: # Section 6.6.2 of t "Trusted Platform Module Library Part 2: Structures Family “2.0†Level 00 Revision 01.38" # - https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf # declare -A codes tss2_tpm2_types='' for dir in "$(pkg-config --variable includedir tss2-esys)" \ /usr/local/include /usr/include; do if [ -f "$dir/tss2/tss2_tpm2_types.h" ]; then tss2_tpm2_types="$dir/tss2/tss2_tpm2_types.h" break fi done if [ -z "$tss2_tpm2_types" ]; then echo "Could not find TSS2 headers" exit 1 fi # Populate the main TPM2_RC values eval $(grep -Po "^#define \K(TPM2_RC.*)" "$tss2_tpm2_types" \ | grep -v '+' \ | sed "s%/*[^/]*/$%%g" \ | sed "s%[[:space:]]*((TPM2_RC)[[:space:]]*%=%g" \ | sed "s%)%%g") # Generate the TPM2_RC array based on TSS2 header varlist="$(sed -rn "s%^#define (TPM2_RC_[^[:space:]]*)[[:space:]]*\(\(TPM2_RC\) \((TPM2_RC[^\)]*)[^/]*/\* ([^\*]*) \*/%\1=\$\(\(\2\)\):\3%p" "$tss2_tpm2_types")" while IFS='=' read key value; do codes[${key}]="${value}" done <<< "${varlist}" fail=0 for key in "${!codes[@]}"; do value="$(printf '0x%03x' "$(eval echo ${codes[$key]%%:*})")" expected_msg="${codes[$key]##*:}" received_msg="$(tpm2 rc_decode ${value} | cut -d':' -f3)" if ! grep -iq "${received_msg# }" <<< "${expected_msg}"; then echo "$value raised an invalid error message" echo " - Expected : ${expected_msg}" echo " - Seen : ${received_msg# }" fail=1 fi done # # Negative tests # if tpm2 rc_decode 0x6666329840938498293849238 &>/dev/null; then echo "Expected \"$cmd\" to fail." fail=1 else true fi exit "$fail" tpm2-tools-5.2/test/integration/tests/readclock.sh000066400000000000000000000006331412464516500223410ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f clock.yaml } trap cleanup EXIT start_up tpm2 readclock > clock.yaml # validate we can get each portion of the YAML file yaml_get_kv clock.yaml time yaml_get_kv clock.yaml clock_info clock yaml_get_kv clock.yaml clock_info reset_count yaml_get_kv clock.yaml clock_info restart_count yaml_get_kv clock.yaml clock_info safe exit 0 tpm2-tools-5.2/test/integration/tests/readpublic.sh000066400000000000000000000031031412464516500225170ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=rsa alg_create_obj=sha256 alg_create_key=hmac file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_readpub_key_pub=opu_"$alg_create_obj"_"$alg_create_key" file_readpub_key_priv=opr_"$alg_create_obj"_"$alg_create_key" file_readpub_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" file_readpub_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj"_"$alg_create_key" file_readpub_output=readpub_"$file_readpub_key_ctx" Handle_readpub=0x81010014 cleanup() { rm -f $file_primary_key_ctx $file_readpub_key_pub $file_readpub_key_priv \ $file_readpub_key_name $file_readpub_key_ctx $file_readpub_output tpm2 evictcontrol -Q -C o -c $Handle_readpub 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" tpm2 clear tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_create_obj -G $alg_create_key -u $file_readpub_key_pub \ -r $file_readpub_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_readpub_key_pub \ -r $file_readpub_key_priv -n $file_readpub_key_name -c $file_readpub_key_ctx tpm2 readpublic -Q -c $file_readpub_key_ctx -o $file_readpub_output tpm2 evictcontrol -Q -C o -c $file_readpub_key_ctx $Handle_readpub rm -f $file_readpub_output tpm2 readpublic -Q -c $Handle_readpub -o $file_readpub_output exit 0 tpm2-tools-5.2/test/integration/tests/rsadecrypt.sh000066400000000000000000000062111412464516500225700ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh file_primary_key_ctx=context.p_B1 file_rsaencrypt_key_pub=opuB1_B8 file_rsaencrypt_key_priv=oprB1_B8 file_rsaencrypt_key_ctx=context_loadext_out_B1_B8 file_rsadecrypt_key_ctx=context_load_out_B1_B8 file_rsaencrypt_key_name=name.load.B1_B8 file_rsa_en_output_data=rsa_en.out file_rsa_de_output_data=rsa_de.out file_input_data=secret.data alg_hash=sha256 alg_primary_key=rsa alg_rsaencrypt_key=rsa cleanup() { rm -f $file_input_data $file_primary_key_ctx $file_rsaencrypt_key_pub \ $file_rsaencrypt_key_priv $file_rsaencrypt_key_ctx \ $file_rsaencrypt_key_name $file_output_data $file_rsa_en_output_data \ $file_rsa_de_output_data $file_rsadecrypt_key_ctx label.dat if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_hash -p foo -G $alg_rsaencrypt_key \ -u $file_rsaencrypt_key_pub -r $file_rsaencrypt_key_priv \ -C $file_primary_key_ctx tpm2 loadexternal -Q -C n -u $file_rsaencrypt_key_pub \ -c $file_rsaencrypt_key_ctx tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data < \ $file_input_data tpm2 load -Q -C $file_primary_key_ctx -u $file_rsaencrypt_key_pub \ -r $file_rsaencrypt_key_priv -n $file_rsaencrypt_key_name \ -c $file_rsadecrypt_key_ctx tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -p foo -o \ $file_rsa_de_output_data $file_rsa_en_output_data # Test the diffeent padding schemes ... tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ -s rsaes < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -p foo -o \ $file_rsa_de_output_data -s rsaes $file_rsa_en_output_data tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ -s null < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -p foo -o \ $file_rsa_de_output_data -s null $file_rsa_en_output_data # Test the label option with a string tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -l mylabel \ -o $file_rsa_en_output_data < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -l mylabel -p foo \ -o $file_rsa_de_output_data $file_rsa_en_output_data # Test the label option with a file echo "my file label" > label.dat tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -l label.dat \ -o $file_rsa_en_output_data < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -l label.dat -p foo \ -o $file_rsa_de_output_data $file_rsa_en_output_data # Test RSA encryption/ decryption with OAEP padding mode tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ -s oaep < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -p foo -o \ $file_rsa_de_output_data -s oaep $file_rsa_en_output_data # Test RSA enc/ dec with OAEP-SHA1 mode tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ -s oaep-sha1 < $file_input_data tpm2 rsadecrypt -Q -c $file_rsadecrypt_key_ctx -p foo -o \ $file_rsa_de_output_data -s oaep-sha1 $file_rsa_en_output_data exit 0 tpm2-tools-5.2/test/integration/tests/rsaencrypt.sh000066400000000000000000000030241412464516500226010ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh file_primary_key_ctx=context.p_B1 file_rsaencrypt_key_pub=opuB1_B8 file_rsaencrypt_key_priv=oprB1_B8 file_rsaencrypt_key_ctx=context_load_out_B1_B8 file_rsaencrypt_key_name=name.load.B1_B8 file_rsa_en_output_data=rsa_en.out file_input_data=secret.data alg_hash=sha256 alg_primary_key=rsa alg_rsaencrypt_key=rsa cleanup() { rm -f $file_input_data $file_primary_key_ctx $file_rsaencrypt_key_pub \ $file_rsaencrypt_key_priv $file_rsaencrypt_key_ctx \ $file_rsaencrypt_key_name $file_rsa_en_output_data if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_hash -G $alg_rsaencrypt_key -u $file_rsaencrypt_key_pub \ -r $file_rsaencrypt_key_priv -C $file_primary_key_ctx tpm2 loadexternal -Q -C n -u $file_rsaencrypt_key_pub \ -c $file_rsaencrypt_key_ctx #./tpm2 rsaencrypt -c context_loadexternal_out6.out -I secret.data -o rsa_en.out tpm2 rsaencrypt -Q -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ $file_input_data # Test stdout output and test that stdin pipe works as well. cat $file_input_data | tpm2 rsaencrypt -c $file_rsaencrypt_key_ctx > /dev/null # Test if RSA encryption is possible with OAEP padding scheme tpm2 rsaencrypt -c $file_rsaencrypt_key_ctx -o $file_rsa_en_output_data \ -s oaep < $file_input_data exit 0 tpm2-tools-5.2/test/integration/tests/selftest.sh000066400000000000000000000004441412464516500222430ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Perform simple selftest tpm2 selftest # Perform full selftest tpm2 selftest --fulltest exit 0 tpm2-tools-5.2/test/integration/tests/send-tcti-cmd.sh000066400000000000000000000004501412464516500230420ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause # skip if tcti-cmd not installed pkg-config --exists tss2-tcti-cmd if [ $? -ne 0 ]; then exit 077 fi source helpers.sh start_up random="$(tpm2 getrandom -T"cmd:tpm2 send" --hex 32)" count="$(echo -n "$random" | wc -c)" test "$count" -eq 64 exit 0 tpm2-tools-5.2/test/integration/tests/send.sh000066400000000000000000000011271412464516500213420ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh # assume this script is run from the test/ directory TPM2_COMMAND_FILE="${abs_srcdir}/test/integration/fixtures/get-capability-tpm-prop-fixed.bin" start_up if [ ! -f "${TPM2_COMMAND_FILE}" ]; then echo "No TPM2 command file, cannot run $0" exit 1 fi # check default stdin(file fd)/stdout tpm2 send < "${TPM2_COMMAND_FILE}" > /dev/null # check default stdin(pipe fd) with output file cat ${TPM2_COMMAND_FILE} | tpm2 send -o /dev/null # check -o out and argument file input tpm2 send -o /dev/null "${TPM2_COMMAND_FILE}" exit 0 tpm2-tools-5.2/test/integration/tests/sessionaudit.sh000066400000000000000000000274641412464516500231370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f \ prim.ctx signing_key.ctx signing_key.pub signing_key.priv \ att.data att.sig cp.hash rp.hash cphash.bin rphash.bin zero.bin if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" # # Get audit digest for a TPM command TPM2_GetRandom using and audit session # tpm2 clear tpm2 createprimary -Q -C e -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 startauthsession -S session.ctx --audit-session tpm2 getrandom 8 -S session.ctx --cphash cp.hash --rphash rp.hash tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx tpm2 flushcontext session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest for a TPM command TPM2_CC_Create in an audit session # tpm2 clear tpm2 createprimary -Q -C e -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 startauthsession -S session.ctx --audit-session tpm2 create -Q -C prim.ctx -u key.pub -r key.priv --cphash cp.hash \ --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest for a TPM command TPM2_CC_Create in an audit session # tpm2 clear tpm2 createprimary -Q -C e -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 createprimary -C o -c prim.ctx -G rsa tpm2 readpublic -c prim.ctx -o prim.pub tpm2 create -C prim.ctx -u key.pub -r key.priv -c key.ctx tpm2 readpublic -c key.ctx -n key.name echo "plaintext" > plain.txt tpm2 makecredential -u prim.pub -s plain.txt -n `xxd -p -c 34 key.name` \ -o cred.secret tpm2 startauthsession -S session.ctx --audit-session tpm2 activatecredential -c key.ctx -C prim.ctx -i cred.secret \ -o act_cred.secret -S session.ctx --cphash cp.hash --rphash rp.hash tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest for a TPM command TPM2_CC_Certify in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c primary.ctx tpm2 create -Q -C primary.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 create -Q -g sha256 -G rsa -u certify.pub -r certify.priv -C primary.ctx tpm2 load -Q -C primary.ctx -u certify.pub -r certify.priv -n certify.name \ -c certify.ctx tpm2 startauthsession -S session.ctx --audit-session tpm2 certify -Q -c primary.ctx -C certify.ctx -g sha256 -o attest.out -s sig.out \ --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest for a TPM command TPM2_CC_CertifyCreation in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx \ -d create.dig -t create.ticket tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 create -G rsa -u rsa.pub -r rsa.priv -C prim.ctx -c certsigningkey.ctx tpm2 startauthsession -S session.ctx --audit-session tpm2 certifycreation -C certsigningkey.ctx -c prim.ctx -d create.dig \ -t create.ticket -g sha256 -f plain -s rsassa \ --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_HierarchyChangeauth in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx \ -d create.dig -t create.ticket tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 startauthsession -S session.ctx --audit-session tpm2 changeauth -c o ownerpassword --cphash cp.hash --rphash rp.hash \ -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_ObjectChangeauth in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx \ -d create.dig -t create.ticket tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 create -Q -C prim.ctx -p foo -u key.pub -r key.priv -c key.ctx tpm2 startauthsession -S session.ctx --audit-session tpm2 changeauth -C prim.ctx -p foo -c key.ctx -r new.priv bar \ --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_ChangeEPS in an audit session # tpm2 clear -Q tpm2 startauthsession -S session.ctx --audit-session tpm2 changeeps --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_ChangePPS in an audit session # tpm2 clear -Q tpm2 startauthsession -S session.ctx --audit-session tpm2 changepps --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_NV_Define in an audit session # tpm2 clear -Q tpm2 startauthsession -S session.ctx --audit-session tpm2 nvdefine 0x1500016 -C o -s 32 -a "ownerread|ownerwrite" \ --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_NV_Extend in an audit session # tpm2 clear -Q tpm2 nvdefine -C o -a "nt=extend|ownerread|policywrite|ownerwrite|writedefine" 1 tpm2 startauthsession -S session.ctx --audit-session echo 'my data' | tpm2 nvextend -C o -i- 1 -S session.ctx \ --cphash cp.hash --rphash rp.hash tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_Unseal in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv echo "plaintext" | \ tpm2 create -C prim.ctx -c key.ctx -u key.pub -r key.priv -i- tpm2 startauthsession -S session.ctx --audit-session tpm2 unseal -c key.ctx --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_nvsetbits in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv echo "plaintext" | \ tpm2 create -C prim.ctx -c key.ctx -u key.pub -r key.priv -i- tpm2 nvdefine 1 -a "authwrite|ownerread|nt=bits" tpm2 startauthsession -S session.ctx --audit-session tpm2 nvsetbits 1 -i 1 --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # Get audit digest: TPM command TPM2_CC_NVRead in an audit session # tpm2 clear -Q tpm2 createprimary -Q -C e -g sha256 -G rsa -c prim.ctx tpm2 create -Q -C prim.ctx -c signing_key.ctx -u signing_key.pub \ -r signing_key.priv tpm2 nvdefine 1 -a "authwrite|ownerread|ownerwrite" -s 32 echo "foo" | tpm2 nvwrite -i- 1 -C o tpm2 startauthsession -S session.ctx --audit-session tpm2 nvread 1 -C o -s 3 --cphash cp.hash --rphash rp.hash -S session.ctx tpm2 getsessionauditdigest -c signing_key.ctx -m att.data -s att.sig \ -S session.ctx tpm2 flushcontext session.ctx dd if=/dev/zero bs=1 count=32 status=none of=zero.bin dd if=cp.hash skip=2 bs=1 count=32 status=none of=cphash.bin dd if=rp.hash skip=2 bs=1 count=32 status=none of=rphash.bin diff \ <( cat zero.bin cphash.bin rphash.bin | openssl dgst -sha256 -binary ) \ <( tail -c 32 att.data ) # # End # exit 0 tpm2-tools-5.2/test/integration/tests/sessionconfig.sh000066400000000000000000000015731412464516500232670ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { rm -f session.ctx if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Start a session and test if session attributes can be modified tpm2 startauthsession -S session.ctx ## Check default session attribute has continuesession set DEFAULT_SESSION_ATTRIBUTE=continuesession tpm2 sessionconfig session.ctx | grep $DEFAULT_SESSION_ATTRIBUTE # Check if session can be marked for encryption SESSION_ENCRYPT_SET=encrypt tpm2 sessionconfig session.ctx --enable-encrypt tpm2 sessionconfig session.ctx | grep $SESSION_ENCRYPT_SET # Check if session can be marked for decryption SESSION_DECRYPT_SET=decrypt tpm2 sessionconfig session.ctx --enable-decrypt tpm2 sessionconfig session.ctx | grep $SESSION_DECRYPT_SET tpm2 flushcontext session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/setclock.sh000066400000000000000000000014541412464516500222230ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh get_new_clock() { tpm2 readclock > clock.yaml local clock=$(yaml_get_kv clock.yaml clock_info clock) # the magic number is enough time where where setting the clock to a point # in the future from where we read it. clock=$(($clock + 100000)) echo -n $clock } cleanup() { tpm2 changeauth -c o -p newowner 2>/dev/null || true tpm2 changeauth -c p -p newplatform 2>/dev/null || true rm -f clock.yaml if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up tpm2 setclock $(get_new_clock) # validate hierarchies and passwords tpm2 changeauth -c o newowner tpm2 changeauth -c p newplatform tpm2 setclock -c o -p newowner $(get_new_clock) tpm2 setclock -c p -p newplatform $(get_new_clock) exit 0 tpm2-tools-5.2/test/integration/tests/setprimarypolicy.sh000066400000000000000000000016471412464516500240370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { tpm2 flushcontext session.ctx 2>/dev/null || true rm -f session.ctx policy.pcr primary.ctx if [ "${1}" != "no-shutdown" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shutdown" tpm2 clear tpm2 changeauth -c e endorsementpassword tpm2 startauthsession -S session.ctx tpm2 policypcr -l sha256:0 -L policy.pcr -S session.ctx tpm2 flushcontext session.ctx tpm2 setprimarypolicy -C e -L policy.pcr -g sha256 -P endorsementpassword # # Try changing the endorsement hierarchy password with the policy # tpm2 startauthsession -S session.ctx --policy-session tpm2 policypcr -l sha256:0 -S session.ctx tpm2 changeauth -c e -p session:session.ctx newendorsementpassword tpm2 flushcontext session.ctx # # Use the new password to create a primary key # tpm2 createprimary -C e -c primary.ctx -P newendorsementpassword exit 0 tpm2-tools-5.2/test/integration/tests/sign.sh000066400000000000000000000241211412464516500213500ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh file_primary_key_ctx=context.p_B1 file_signing_key_pub=opuB1_B8 file_signing_key_priv=oprB1_B8 file_signing_key_ctx=context_load_out_B1_B8 file_signing_key_name=name.load.B1_B8 file_signing_key_pub_pem=oppB1_B8 file_input_data=secret.data file_input_digest=secret.digest file_output_data=sig.4 file_output_ticket=secret.ticket file_output_hash=secret.hash rsa_key_type=rsa2048 ecc_key_type=ecc256 handle_signing_key=0x81010005 alg_hash=sha256 alg_primary_key=rsa cleanup() { rm -f $file_input_data $file_primary_key_ctx $file_signing_key_pub \ $file_signing_key_priv $file_signing_key_ctx $file_signing_key_name \ $file_output_data $file_input_digest $file_output_ticket \ $file_output_hash $file_signing_key_pub_pem tpm2 evictcontrol -Q -Co -c $handle_signing_key 2>/dev/null || true if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT test_symmetric() { local alg_signing_key=$1 echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_hash -G $alg_signing_key -u $file_signing_key_pub \ -r $file_signing_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \ -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash \ -o $file_output_data $file_input_data rm -f $file_output_data tpm2 evictcontrol -Q -C o -c $file_signing_key_ctx $handle_signing_key tpm2 sign -Q -c $handle_signing_key -g $alg_hash -o $file_output_data \ $file_input_data rm -f $file_output_data # generate hash and test validation tpm2 hash -Q -C e -g $alg_hash -o $file_output_hash -t $file_output_ticket \ $file_input_data tpm2 sign -Q -c $handle_signing_key -g $alg_hash -o $file_output_data \ -t $file_output_ticket $file_input_data rm -f $file_output_data # test with digest, no validation shasum -a 256 $file_input_data | awk '{ print "000000 " $1 }' | xxd -r -c 32 > \ $file_input_digest tpm2 sign -Q -c $handle_signing_key -g $alg_hash -d -o $file_output_data \ $file_input_digest rm -f $file_output_data } create_signature() { local sign_scheme=$1 if [ "$sign_scheme" = "" ]; then tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash -f plain \ -o $file_output_data $file_input_data else tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash -s $sign_scheme \ -f plain -o $file_output_data $file_input_data fi } get_openssl_version_number() { # Ubuntu 14.04, 16.04, 18.04 and 19.04: # "OpenSSL 1.0.1f 6 Jan 2014" # "OpenSSL 1.0.2g 1 Mar 2016" # "OpenSSL 1.1.0g 2 Nov 2017" # "OpenSSL 1.1.1b 26 Feb 2019" if [ -z "$1" ]; then local openssl_version=$(openssl version -v) else local openssl_version="$1" fi local openssl_version_parsed=$(echo "$openssl_version" | sed -r 's/^OpenSSL ([0-9]+)\.([0-9]+)\.([0-9]+).*$/\1 \2 \3/') local openssl_v1=$(echo $openssl_version_parsed | cut -d ' ' -f 1) local openssl_v2=$(echo $openssl_version_parsed | cut -d ' ' -f 2) local openssl_v3=$(echo $openssl_version_parsed | cut -d ' ' -f 3) local openssl_version_num=$(("$openssl_v1"<<16 + "$openssl_v2"<<8 + "$openssl_v3")) echo "$openssl_version_num" } verify_signature() { local sign_scheme=$1 if [ "$sign_scheme" = "rsapss" ] ; then # Explanation: # RSA-PSS has a parameter called salt length. # You need to know what value of salt length was used to create the # signature in order to verify the signature. # OpenSSL can actually automatically determine the correct value, so # strictly speaking we could just let it and simplify this test a lot. # But, if you want to verify the signature using some other API, # you might need to know the salt length used by the TPM to produce the # signature. # It can be either "digest" or "max". You can use openssl the check # whether it's "digest", and if it's not then it's "max". # From TCG TPM 2.0, Part 1: Architecture, Appendix B.7 # "... the random salt length will be the largest size allowed by the # key size and message digest size." # From NIST FIPS PUB 186-4, Section 5.5 # "... the length (in bytes) of the salt (sLen) shall satisfy # 0 <= sLen <= hLen, where hLen is the length of the hash function # output block (in bytes)." # From TCG FIPS 140-2 Guidance for TPM 2.0, Section 5.2.1.3 # "If the TPM implementation is required to be compliant with FIPS 186-4, # then the random salt length will be the largest size allowed by that # specification." # Thus, if the TPM is in "FIPS mode", PSS salt length is "digest", # otherwise PSS salt length is "max". # Either one is accepted by this test. # The IBM TPM software emulator (at least the version in ibmtpm1332.tar.gz) # uses "digest". local openssl_current_version_num=$(get_openssl_version_number) local openssl_1_1_1_version_num=$(get_openssl_version_number "OpenSSL 1.1.1") # Explanation: # In version 1.1.1, openssl switched from "-1","-2" (meaning "digest" and # "auto" correspondingly) to "digest", "max" and "auto". # See section "rsa_pss_saltlen:len" in # https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/doc/man1/pkeyutl.pod # and same section in # https://github.com/openssl/openssl/blob/OpenSSL_1_1_0-stable/doc/apps/pkeyutl.pod if [ "$openssl_current_version_num" -ge "$openssl_1_1_1_version_num" ] ; then local pss_salt_len_arg_digest="digest" local pss_salt_len_arg_max="max" local pss_salt_len_arg_auto="auto" else local pss_salt_len_arg_digest="-1" local pss_salt_len_arg_auto="-2" fi openssl pkeyutl -verify \ -in $file_input_digest \ -sigfile $file_output_data \ -pubin \ -inkey $file_signing_key_pub_pem \ -keyform pem \ -pkeyopt digest:$alg_hash \ -pkeyopt rsa_padding_mode:pss \ -pkeyopt rsa_pss_saltlen:$pss_salt_len_arg_digest \ |& grep -q '^Signature Verified Successfully' \ || \ openssl pkeyutl -verify \ -in $file_input_digest \ -sigfile $file_output_data \ -pubin \ -inkey $file_signing_key_pub_pem \ -keyform pem \ -pkeyopt digest:$alg_hash \ -pkeyopt rsa_padding_mode:pss \ -pkeyopt rsa_pss_saltlen:$pss_salt_len_arg_auto \ |& grep -q '^Signature Verified Successfully' else openssl pkeyutl -verify \ -in $file_input_digest \ -sigfile $file_output_data \ -pubin \ -inkey $file_signing_key_pub_pem \ -keyform pem \ -pkeyopt digest:$alg_hash \ |& grep -q '^Signature Verified Successfully' fi } test_asymmetric() { local alg_signing_key=$1 head -c30 /dev/urandom > $file_input_data shasum -a 256 $file_input_data | awk '{ print "000000 " $1 }' | \ xxd -r -c 32 > $file_input_digest tpm2 clear tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_hash -G $alg_signing_key -u $file_signing_key_pub \ -r $file_signing_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \ -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx tpm2 readpublic -Q -c $file_signing_key_ctx --format=pem \ -o $file_signing_key_pub_pem local sign_scheme if [ "$alg_signing_key" = "$rsa_key_type" ] ; then for sign_scheme in "" "rsassa" "rsapss" do create_signature $sign_scheme verify_signature $sign_scheme rm -f $file_output_data done fi if [ "$alg_signing_key" = "$ecc_key_type" ]; then for sign_scheme in "" "ecdsa" do create_signature $sign_scheme verify_signature $sign_scheme rm -f $file_output_data done fi } start_up cleanup "no-shut-down" # make sure commands failing inside the function will cause the script to fail! ( set -e test_symmetric "hmac" cleanup "no-shut-down" ) for key_type in $rsa_key_type $ecc_key_type do # make sure commands failing inside the function will cause the script # to fail! ( set -e test_asymmetric $key_type cleanup "no-shut-down" ) done # Test signing with ecdaa scheme head -c30 /dev/urandom | openssl dgst -sha256 -binary > test.rnd tpm2 clear tpm2 createprimary -Q -C o -c prim.ctx -g sha256 -G rsa tpm2 create -Q -g sha256 -G ecc256:ecdaa -u key.pub -r key.priv -C prim.ctx tpm2 load -C prim.ctx -u key.pub -r key.priv -n key.name -c key.ctx tpm2 readpublic -c key.ctx --format=pem -o key.pem tpm2 commit -c key.ctx -t commit.ctr --eccpoint-K K.bin --eccpoint-L L.bin -u E.bin tpm2 commit -c key.ctx -t commit.ctr --eccpoint-K K.bin --eccpoint-L L.bin -u E.bin tpm2 sign -c key.ctx -g sha256 -o test.sig test.rnd -s ecdaa --commit-index 1 tpm2 sign -c key.ctx -g sha256 -o test.sig test.rnd -s ecdaa # Test that invalid password returns the proper code cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 createprimary -Q -c $file_primary_key_ctx tpm2 create -Q -C $file_primary_key_ctx -u $file_signing_key_pub \ -r $file_signing_key_priv -p "mypassword" tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \ -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx # Negative test, remove error handler trap - ERR tpm2 sign -Q -p "badpassword" -c $file_signing_key_ctx -g $alg_hash \ -o $file_output_data $file_input_data if [ $? != 3]; then echo "Expected RC 3, got: $?" 1>&2 fi trap onerror ERR exit 0 tpm2-tools-5.2/test/integration/tests/startup.sh000066400000000000000000000003601412464516500221110ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh start_up tpm2 startup --clear tpm2 startup # rather than incur another simulator startup just test shutdown # in this test as well. tpm2 shutdown tpm2 shutdown --clear exit 0 tpm2-tools-5.2/test/integration/tests/stirrandom.sh000066400000000000000000000017451412464516500226010ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh goodfile=$(mktemp) bigfile=$(mktemp) { dd if=/dev/urandom of="${bigfile}" bs=1 count=256 dd if=/dev/urandom of="${goodfile}" bs=1 count=42 } &>/dev/null cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down rm -f "${bigfile}" rm -f "${goodfile}" fi } trap cleanup EXIT start_up cleanup "no-shut-down" # Sending bytes from stdin (pipe) echo -n "return 4" | tpm2 stirrandom -V 2>&1 1>/dev/null | \ grep -q "Submitting 8 bytes to TPM" # Sending bytes from stdin (file) tpm2 stirrandom -V < "${goodfile}" 2>&1 1>/dev/null | \ grep -q "Submitting 42 bytes to TPM" # Sending bytes from a file path tpm2 stirrandom "${goodfile}" -V 2>&1 1>/dev/null | \ grep -q "Submitting 42 bytes to TPM" # Try to read more than 128 bytes from file and get an error if tpm2 stirrandom "${bigfile}"; then echo "tpm2 stirrandom didn't fail on exceeding requested size" exit 1 else true fi exit 0 tpm2-tools-5.2/test/integration/tests/symlink.sh000066400000000000000000000032241412464516500220770ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh TMP="$(mktemp -d)" cleanup() { rm -rf "$TMP" } trap cleanup EXIT start_up # # Positive tests: # fail=0 TPM2_TOOL="$(which tpm2)" if [ -z "$TPM2_TOOL" ]; then echo "unable to locate tpm2 tool" fail=1 fi #echo "Using $TPM2_TOOL" # # Disabling this test and leaving a note for traceability because # disabling/ deleting tests without rational is a bad thing. # # Executing tpm2 without argument should now execute the man-page. # ## no arguments should produce at least ten lines of output #NUM_TOOLS=$(tpm2 2>&1 | wc -l) #if [ -z "$NUM_TOOLS" ] || [ "$NUM_TOOLS" -lt 10 ]; then # echo "tpm2 with no arguments did not produce list of tools" # fail=1 #fi # busybox style if ! tpm2 readclock &>/dev/null ; then echo "busybox style failed" fail=1 fi # with tpm2_ prefix ln -s "$TPM2_TOOL" "$TMP/tpm2_readclock" if ! "$TMP/tpm2_readclock" &>/dev/null ; then echo "tpm2_ prefix style failed" fail=1 fi # without prefix ln -s "$TPM2_TOOL" "$TMP/readclock" if ! "$TMP/readclock" &>/dev/null ; then echo "no prefix style failed" fail=1 fi # # Negative tests # # command not found, as busybox style if tpm2 bad-command &>/dev/null ; then echo "Expected 'tmp2 bad-command' to fail." fail=1 fi # command not found, with tpm2_ prefix ln -s "$TPM2_TOOL" "$TMP/tmp2_bad-command" if "$TMP/tmp2_bad-command" &>/dev/null ; then echo "Expected 'tmp2_bad-command' to fail." fail=1 fi # command not found, without tpm2_ prefix ln -s "$TPM2_TOOL" "$TMP/bad-command" if "$TMP/bad-command" &>/dev/null ; then echo "Expected 'bad-command' to fail." fail=1 fi exit "$fail" tpm2-tools-5.2/test/integration/tests/testparms.sh000066400000000000000000000037401412464516500224360ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh cleanup() { if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" aesmodes="$(populate_algs "details['encrypting'] and details['symmetric']")" hashalgs="$(populate_algs "details['hash'] and not details['method'] \ and not details['signing'] \ and not details['symmetric'] \ and alg is not None")" eccmethods="$(populate_algs "details['signing'] and not details['hash'] and \"ec\" in alg")" rsamethods="$(populate_algs "details['signing'] and not details['hash'] and \"rsa\" in alg")" # Test that common algorithms are supported for i in "rsa" "xor" "hmac" "ecc" "keyedhash"; do tpm2 testparms "${i}" done # Test that RSA signing schemes are supported for i in ${rsamethods}; do echo "tpm2 testparms rsa:${i}" tpm2 testparms "rsa:${i}" done # Test that ECC signing schemes are supported for i in ${eccmethods}; do tpm2 testparms "ecc:${i}" done # Test that aes modes are supported for i in ${aesmodes}; do tpm2 testparms "aes128${i}" done # Test that xor on hash algs is supported for i in ${hashalgs}; do tpm2 testparms "xor:${i}" done # Test that hmac on hash algs is supported for i in ${hashalgs}; do tpm2 testparms "hmac:${i}" done # Test that null algorithm raise an error (error from software stack) if ! tpm2 testparms "null" 2>&1 1>/dev/null | \ grep -q "Invalid or unsupported by the tool : null"; then echo "tpm2 testparms with 'null' algorithm didn't fail" exit 1 else true fi # Attempt to specify a suite that is not supported (error from TPM) if tpm2 getcap ecc-curves | grep -q TPM2_ECC_NIST_P521; then if tpm2 testparms "ecc521:ecdsa:camellia" &>/dev/null; then echo "tpm2 testparms succeeded while it shouldn't or TPM failed" exit 1 else true fi fi exit 0 tpm2-tools-5.2/test/integration/tests/toggle_options.sh000066400000000000000000000103011412464516500234370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh # We don't need a TPM for this test, so unset the EXIT handler. trap - EXIT # Since this only tests tools options and docs # and is not portable skip it on FreeBSD if [ "$OS" == "FreeBSD" ]; then exit 0 fi srcdir="$(readlink -e "$(dirname "$0")")" toolsdir="$(readlink -e "${srcdir}"/../../../tools)" mandir="$(readlink -e "${srcdir}"/../../../man)" # Provide a sanitizing test on whether a toggle # is effectively taken into account on option parsing. # Also, checks if the options are documented in the # respective man file consistently. # Functionnal check is left for dedicated test cases. # # It assumes that the layout for describing toggles and # option is coherent among the tools function check_toggle() { toggle=${1} if [ ${#toggle} -ne 1 ]; then echo "toggle should be one character only !" exit 254 fi for i in $(grep "'${toggle}'[[:space:]]*}" "${toolsdir}"/*.c | \ sed "s%[[:space:]]*%%g"); do # An example: # i: tools/tpm2_nvdefine.c:{"hierarchy",required_argument,NULL,'a'}, # filename: tools/tpm2_nvdefine.c # match: {"hierarchy",required_argument,NULL,'a'}, # option: a # option_long: hierarchy # optionlist: "x:a:s:b:P:p:L:" # getcase: case'a': filename=${i%%:*}; match=${i##*:}; option="$(sed -r "s%.*'([^'])'.*%\1%g" <<< "${match}")" option_long="$(grep -oP '(?<={").*(?=")' <<< "${match}")" optionlist="$(grep -R "tpm2_options_new" "${filename}" | \ sed -r 's%.*("[^"]+").*%\1%g')" getcase="$(grep "case '${option}'" "${filename}" | \ sed "s%[[:space:]]*%%g")" echo "filename: $filename" echo " match: $match" echo " option: $option" echo " option_long: $option_long" echo " optionlist: $optionlist" echo " getcase: $getcase" if [[ "${filename}" =~ tpm2_options.c$ ]]; then continue fi if ! grep -q "${option}" <<< "${optionlist}"; then echo "$filename: option -$option (--$option_long) not found in \ option list $optionlist" exit 1 fi if ! test -n "${getcase}"; then echo "$filename: switch case '$option' not found for option \ -$option (--$option_long)" exit 1 fi ####################### check man page ####################### man_filename="$(basename $filename)" # tpm2_nvdefine.c man_filename="$mandir/${man_filename%.*}.1.md" # man/tpm2_nvdefine.1.md man=$(cat "$man_filename") # resolve markdown includes man_resolved="$man" for md_include in $(grep -Po '(?<=\]\()common/.*(?=\))' <<< "$man"); do man_resolved="$man_resolved $(cat $mandir/$md_include)" done # search markdown for option (short and long) man_opt=$(grep -oe "\*\*-$option\*\*, \*\*\\\--$option_long\*\*" \ <<< "$man_resolved") || true if [ -n "$man_opt" ]; then echo " man_opt: $man_opt" else echo "$filename: missing option -$option/--$option_long in \ $man_filename" exit 1 fi done } fail=0 # For each detected option toggle, check if it is actually declared to be used # and documented for i in $(grep -rn "case '.'" "${toolsdir}"/*.c | \ cut -d"'" -f2-2 | sort | uniq); do check_toggle "${i}" done # For each documented option toggle in the man pages, look if it is present in # the code for j in $(grep -oe "\*\*-.\*\*, \*\*\\\--.*\*\*" "${mandir}"/*.1.md | \ sed -r 's/\s//g' ); do filename=${j%%:*}; option="$(grep -oP '(?<=\*\*-).(?=\*\*)' <<< "$j")" option_long="$(grep -oP '(?<=\*\*\\\--).*(?=\*\*)' <<< "$j")" c_filename=$(basename ${filename%.1.md}).c echo "$filename: looking for -$option (--$option_long) in $c_filename" found=$(grep -r "case '${option}'" "$toolsdir" --include="$c_filename") \ || true if [ -z "$found" ]; then echo "$filename: missing option -$option (--$option_long) in \ $c_filename" exit 1 fi done exit $fail tpm2-tools-5.2/test/integration/tests/unseal.sh000066400000000000000000000113321412464516500216770ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh alg_primary_obj=sha256 alg_primary_key=ecc alg_create_obj=sha256 pcr_specification=sha256:0,1,2,3+sha1:0,1,2,3 file_pcr_value=pcr.bin file_input_data=secret.data file_policy=policy.data file_primary_key_ctx=context.p_"$alg_primary_obj"_"$alg_primary_key" file_unseal_key_pub=opu_"$alg_create_obj" file_unseal_key_priv=opr_"$alg_create_obj" file_unseal_key_ctx=ctx_load_out_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj" file_unseal_key_name=name.load_"$alg_primary_obj"_"$alg_primary_key"-\ "$alg_create_obj" file_unseal_output_data=usl_"$file_unseal_key_ctx" secret="12345678" cleanup() { rm -f $file_input_data $file_primary_key_ctx $file_unseal_key_pub \ $file_unseal_key_priv $file_unseal_key_ctx $file_unseal_key_name \ $file_unseal_output_data $file_pcr_value $file_policy if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo $secret > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_primary_obj -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_create_obj -u $file_unseal_key_pub \ -r $file_unseal_key_priv -i $file_input_data -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx tpm2 unseal -Q -c $file_unseal_key_ctx -o $file_unseal_output_data cmp -s $file_unseal_output_data $file_input_data # Test -i using stdin via pipe rm $file_unseal_key_pub $file_unseal_key_priv $file_unseal_key_name \ $file_unseal_key_ctx cat $file_input_data | tpm2 create -Q -g $alg_create_obj \ -u $file_unseal_key_pub -r $file_unseal_key_priv -i- -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx tpm2 unseal -Q -c $file_unseal_key_ctx -o $file_unseal_output_data cmp -s $file_unseal_output_data $file_input_data # Test using a PCR policy for auth and use file based stdin for -i rm $file_unseal_key_pub $file_unseal_key_priv $file_unseal_key_name \ $file_unseal_key_ctx tpm2 pcrread -Q -o $file_pcr_value $pcr_specification tpm2 createpolicy -Q --policy-pcr -l $pcr_specification -f $file_pcr_value \ -L $file_policy tpm2 create -Q -g $alg_create_obj -u $file_unseal_key_pub \ -r $file_unseal_key_priv -i- -C $file_primary_key_ctx -L $file_policy \ -a 'fixedtpm|fixedparent' <<< $secret tpm2 load -Q -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx unsealed=`tpm2 unseal -V --object-context $file_unseal_key_ctx \ -p pcr:$pcr_specification=$file_pcr_value` test "$unsealed" == "$secret" # Test that unseal fails if a PCR policy isn't provided trap - ERR tpm2 unseal -c $file_unseal_key_ctx 2> /dev/null if [ $? != 1 ]; then echo "tpm2 unseal didn't fail without a PCR policy!" exit 1 fi # Test that unseal fails if PCR state isn't the same as the defined PCR policy tpm2 pcrextend 0:sha1=6c10289a8da7f774cf67bd2fc8502cd4b585346a tpm2 unseal -c $file_unseal_key_ctx -p pcr:$pcr_specification 2> /dev/null if [ $? != 1 ]; then echo "tpm2 unseal didn't fail with a PCR state different than the policy!" exit 1 fi # Test that the object can be unsealed without a policy but a password trap onerror ERR rm $file_unseal_key_pub $file_unseal_key_priv $file_unseal_key_name \ $file_unseal_key_ctx tpm2 pcrread -Q -o $file_pcr_value $pcr_specification tpm2 createpolicy -Q --policy-pcr -l $pcr_specification -f $file_pcr_value \ -L $file_policy tpm2 create -Q -g $alg_create_obj -u $file_unseal_key_pub \ -r $file_unseal_key_priv -i- -C $file_primary_key_ctx -L $file_policy \ -p secretpass <<< $secret tpm2 load -Q -C $file_primary_key_ctx -u $file_unseal_key_pub \ -r $file_unseal_key_priv -n $file_unseal_key_name -c $file_unseal_key_ctx unsealed=`tpm2 unseal -c $file_unseal_key_ctx -p secretpass` test "$unsealed" == "$secret" # Test that unseal fails when using a wrong password trap - ERR tpm2 unseal -c $file_unseal_key_ctx -p wrongpass 2> /dev/null if [ $? != 3 ]; then echo "tpm2 unseal didn't fail when using a wrong object password!" exit 1 fi # Test unsealing with encrypted sessions trap onerror ERR tpm2 createprimary -Q -C o -c prim.ctx tpm2 startauthsession -S enc_session.ctx --hmac-session -c prim.ctx tpm2 sessionconfig enc_session.ctx --disable-encrypt tpm2 create -Q -C prim.ctx -u seal_key.pub -r seal_key.priv -c seal_key.ctx \ -p sealkeypass -i- <<< $secret -S enc_session.ctx tpm2 sessionconfig enc_session.ctx --enable-encrypt unsealed=`tpm2 unseal -c seal_key.ctx -p sealkeypass -S enc_session.ctx` test "$unsealed" == "$secret" tpm2 flushcontext enc_session.ctx exit 0 tpm2-tools-5.2/test/integration/tests/verifysignature.sh000066400000000000000000000037711412464516500236460ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause source helpers.sh file_primary_key_ctx=context.p_B1 file_signing_key_pub=opuB1_B8 file_signing_key_priv=oprB1_B8 file_signing_key_ctx=context_load_out_B1_B8 file_signing_key_name=name.load.B1_B8 file_input_data=secret.data file_output_data=sig.4 file_verify_tk_data=tickt_verify_sig.4 file_input_data_hash=secret_hash.data file_input_data_hash_tk=secret_hash_tk.data handle_signing_key=0x81010005 alg_hash=sha256 alg_primary_key=rsa alg_signing_key=rsa cleanup() { rm -f $file_primary_key_ctx $file_signing_key_pub $file_signing_key_priv \ $file_signing_key_ctx $file_signing_key_name $file_output_data \ $file_verify_tk_data $file_input_data_hash $file_input_data_hash_tk \ $file_input_data if [ "$1" != "no-shut-down" ]; then shut_down fi } trap cleanup EXIT start_up cleanup "no-shut-down" echo "12345678" > $file_input_data tpm2 clear tpm2 createprimary -Q -C e -g $alg_hash -G $alg_primary_key \ -c $file_primary_key_ctx tpm2 create -Q -g $alg_hash -G $alg_signing_key -u $file_signing_key_pub \ -r $file_signing_key_priv -C $file_primary_key_ctx tpm2 load -Q -C $file_primary_key_ctx -u $file_signing_key_pub \ -r $file_signing_key_priv -n $file_signing_key_name -c $file_signing_key_ctx tpm2 sign -Q -c $file_signing_key_ctx -g $alg_hash -o $file_output_data \ $file_input_data tpm2 verifysignature -Q -c $file_signing_key_ctx -g $alg_hash \ -m $file_input_data -s $file_output_data -t $file_verify_tk_data tpm2 hash -Q -C n -g $alg_hash -o $file_input_data_hash \ -t $file_input_data_hash_tk $file_input_data rm -f $file_verify_tk_data tpm2 verifysignature -Q -c $file_signing_key_ctx -d $file_input_data_hash \ -s $file_output_data -t $file_verify_tk_data rm -f $file_verify_tk_data $file_signing_key_ctx -rf tpm2 loadexternal -Q -C n -u $file_signing_key_pub -c $file_signing_key_ctx tpm2 verifysignature -Q -c $file_signing_key_ctx -g $alg_hash \ -m $file_input_data -s $file_output_data -t $file_verify_tk_data exit 0 tpm2-tools-5.2/test/unit/000077500000000000000000000000001412464516500153465ustar00rootroot00000000000000tpm2-tools-5.2/test/unit/esys_stubs.h000066400000000000000000000044001412464516500177200ustar00rootroot00000000000000/* * Various helper functions copy/pasted from tpm2-tss to help mock ESAPI * interfaces such that we can unit test our code. */ #ifndef ESYS_STUBS_H #define ESYS_STUBS_H #include #include #define TCTI_FAKE_MAGIC 0x46414b4500000000ULL /* 'FAKE\0' */ #define TCTI_FAKE_VERSION 0x1 typedef struct { uint64_t magic; uint32_t version; TSS2_TCTI_TRANSMIT_FCN transmit; TSS2_TCTI_RECEIVE_FCN receive; TSS2_RC(*finalize) (TSS2_TCTI_CONTEXT * tctiContext); TSS2_RC(*cancel) (TSS2_TCTI_CONTEXT * tctiContext); TSS2_RC(*getPollHandles) (TSS2_TCTI_CONTEXT * tctiContext, TSS2_TCTI_POLL_HANDLE * handles, size_t * num_handles); TSS2_RC(*setLocality) (TSS2_TCTI_CONTEXT * tctiContext, uint8_t locality); } TSS2_TCTI_CONTEXT_FAKE; TSS2_TCTI_POLL_HANDLE rev[] = { {.fd=66, .events=1, .revents=0}, {.fd=99, .events=1, .revents=0} }; static TSS2_RC tcti_fake_getpollhandles(TSS2_TCTI_CONTEXT * tctiContext, TSS2_TCTI_POLL_HANDLE * handles, size_t * num_handles) { (void) tctiContext; if (handles == NULL) { *num_handles = 2; return TSS2_RC_SUCCESS; } assert_int_equal(*num_handles, 2); memcpy(&handles[0], &rev[0], sizeof(rev)); return TSS2_RC_SUCCESS; } static TSS2_RC tcti_fake_initialize(TSS2_TCTI_CONTEXT * tctiContext, size_t * contextSize) { TSS2_TCTI_CONTEXT_FAKE *tcti_fake = (TSS2_TCTI_CONTEXT_FAKE *) tctiContext; if (tctiContext == NULL && contextSize == NULL) { return TSS2_TCTI_RC_BAD_VALUE; } else if (tctiContext == NULL) { *contextSize = sizeof(*tcti_fake); return TSS2_RC_SUCCESS; } /* Init TCTI context */ memset(tcti_fake, 0, sizeof(*tcti_fake)); TSS2_TCTI_MAGIC(tctiContext) = TCTI_FAKE_MAGIC; TSS2_TCTI_VERSION(tctiContext) = TCTI_FAKE_VERSION; TSS2_TCTI_TRANSMIT(tctiContext) = (void*)1; TSS2_TCTI_RECEIVE(tctiContext) = (void*)1; TSS2_TCTI_FINALIZE(tctiContext) = NULL; TSS2_TCTI_CANCEL(tctiContext) = NULL; TSS2_TCTI_GET_POLL_HANDLES(tctiContext) = tcti_fake_getpollhandles; TSS2_TCTI_SET_LOCALITY(tctiContext) = NULL; return TSS2_RC_SUCCESS; } #endif /* ESYS_STUBS_H */ tpm2-tools-5.2/test/unit/test_cc_util.c000066400000000000000000000154431412464516500202020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_cc_util.h" #include "tpm2_util.h" static void test_tpm2_cc_util_from_str_null_str_ptr(void **state) { UNUSED(state); TPM2_CC cc; bool result = tpm2_cc_util_from_str(NULL, &cc); assert_false(result); } static void test_tpm2_cc_util_from_str_null_cc_ptr(void **state) { UNUSED(state); bool result = tpm2_cc_util_from_str("duplicate", NULL); assert_false(result); } static void test_tpm2_cc_util_from_str_null_ptrs(void **state) { UNUSED(state); bool result = tpm2_cc_util_from_str(NULL, NULL); assert_false(result); } static void test_tpm2_cc_util_from_str_invalid_str(void **state) { UNUSED(state); TPM2_CC cc = 0; bool result = tpm2_cc_util_from_str("nofound", &cc); assert_false(result); assert_int_equal(cc, 0); } static void test_tpm2_cc_util_from_str_empty_str(void **state) { UNUSED(state); TPM2_CC cc = 0; bool result = tpm2_cc_util_from_str("", &cc); assert_false(result); assert_int_equal(cc, 0); } static void test_tpm2_cc_util_from_str_valid_hex_str(void **state) { UNUSED(state); TPM2_CC cc = 0; bool result = tpm2_cc_util_from_str("0x42", &cc); assert_true(result); assert_int_equal(cc, 0x42); } static void test_tpm2_cc_util_to_str_unknown(void **state) { UNUSED(state); const char *cc_name = tpm2_cc_util_to_str(TPM2_CC_LAST + 1); assert_null(cc_name); } typedef struct cc_map cc_map; struct cc_map { TPM2_CC cc; const char *str; }; #define ADDCC(c) { .str = #c, .cc = c } static const cc_map _g_map[] = { ADDCC(TPM2_CC_NV_UndefineSpaceSpecial), ADDCC(TPM2_CC_EvictControl), ADDCC(TPM2_CC_HierarchyControl), ADDCC(TPM2_CC_NV_UndefineSpace), ADDCC(TPM2_CC_ChangeEPS), ADDCC(TPM2_CC_ChangePPS), ADDCC(TPM2_CC_Clear), ADDCC(TPM2_CC_ClearControl), ADDCC(TPM2_CC_ClockSet), ADDCC(TPM2_CC_HierarchyChangeAuth), ADDCC(TPM2_CC_NV_DefineSpace), ADDCC(TPM2_CC_PCR_Allocate), ADDCC(TPM2_CC_PCR_SetAuthPolicy), ADDCC(TPM2_CC_PP_Commands), ADDCC(TPM2_CC_SetPrimaryPolicy), ADDCC(TPM2_CC_FieldUpgradeStart), ADDCC(TPM2_CC_ClockRateAdjust), ADDCC(TPM2_CC_CreatePrimary), ADDCC(TPM2_CC_NV_GlobalWriteLock), ADDCC(TPM2_CC_GetCommandAuditDigest), ADDCC(TPM2_CC_NV_Increment), ADDCC(TPM2_CC_NV_SetBits), ADDCC(TPM2_CC_NV_Extend), ADDCC(TPM2_CC_NV_Write), ADDCC(TPM2_CC_NV_WriteLock), ADDCC(TPM2_CC_DictionaryAttackLockReset), ADDCC(TPM2_CC_DictionaryAttackParameters), ADDCC(TPM2_CC_NV_ChangeAuth), ADDCC(TPM2_CC_PCR_Event), ADDCC(TPM2_CC_PCR_Reset), ADDCC(TPM2_CC_SequenceComplete), ADDCC(TPM2_CC_SetAlgorithmSet), ADDCC(TPM2_CC_SetCommandCodeAuditStatus), ADDCC(TPM2_CC_FieldUpgradeData), ADDCC(TPM2_CC_IncrementalSelfTest), ADDCC(TPM2_CC_SelfTest), ADDCC(TPM2_CC_Startup), ADDCC(TPM2_CC_Shutdown), ADDCC(TPM2_CC_StirRandom), ADDCC(TPM2_CC_ActivateCredential), ADDCC(TPM2_CC_Certify), ADDCC(TPM2_CC_PolicyNV), ADDCC(TPM2_CC_CertifyCreation), ADDCC(TPM2_CC_Duplicate), ADDCC(TPM2_CC_GetTime), ADDCC(TPM2_CC_GetSessionAuditDigest), ADDCC(TPM2_CC_NV_Read), ADDCC(TPM2_CC_NV_ReadLock), ADDCC(TPM2_CC_ObjectChangeAuth), ADDCC(TPM2_CC_PolicySecret), ADDCC(TPM2_CC_Rewrap), ADDCC(TPM2_CC_Create), ADDCC(TPM2_CC_ECDH_ZGen), ADDCC(TPM2_CC_HMAC), ADDCC(TPM2_CC_Import), ADDCC(TPM2_CC_Load), ADDCC(TPM2_CC_Quote), ADDCC(TPM2_CC_RSA_Decrypt), ADDCC(TPM2_CC_HMAC_Start), ADDCC(TPM2_CC_SequenceUpdate), ADDCC(TPM2_CC_Sign), ADDCC(TPM2_CC_Unseal), ADDCC(TPM2_CC_PolicySigned), ADDCC(TPM2_CC_ContextLoad), ADDCC(TPM2_CC_ContextSave), ADDCC(TPM2_CC_ECDH_KeyGen), ADDCC(TPM2_CC_EncryptDecrypt), ADDCC(TPM2_CC_FlushContext), ADDCC(TPM2_CC_LoadExternal), ADDCC(TPM2_CC_MakeCredential), ADDCC(TPM2_CC_NV_ReadPublic), ADDCC(TPM2_CC_PolicyAuthorize), ADDCC(TPM2_CC_PolicyAuthValue), ADDCC(TPM2_CC_PolicyCommandCode), ADDCC(TPM2_CC_PolicyCounterTimer), ADDCC(TPM2_CC_PolicyCpHash), ADDCC(TPM2_CC_PolicyLocality), ADDCC(TPM2_CC_PolicyNameHash), ADDCC(TPM2_CC_PolicyOR), ADDCC(TPM2_CC_PolicyTicket), ADDCC(TPM2_CC_ReadPublic), ADDCC(TPM2_CC_RSA_Encrypt), ADDCC(TPM2_CC_StartAuthSession), ADDCC(TPM2_CC_VerifySignature), ADDCC(TPM2_CC_ECC_Parameters), ADDCC(TPM2_CC_FirmwareRead), ADDCC(TPM2_CC_GetCapability), ADDCC(TPM2_CC_GetRandom), ADDCC(TPM2_CC_GetTestResult), ADDCC(TPM2_CC_Hash), ADDCC(TPM2_CC_PCR_Read), ADDCC(TPM2_CC_PolicyPCR), ADDCC(TPM2_CC_PolicyRestart), ADDCC(TPM2_CC_ReadClock), ADDCC(TPM2_CC_PCR_Extend), ADDCC(TPM2_CC_PCR_SetAuthValue), ADDCC(TPM2_CC_NV_Certify), ADDCC(TPM2_CC_EventSequenceComplete), ADDCC(TPM2_CC_HashSequenceStart), ADDCC(TPM2_CC_PolicyPhysicalPresence), ADDCC(TPM2_CC_PolicyDuplicationSelect), ADDCC(TPM2_CC_PolicyGetDigest), ADDCC(TPM2_CC_TestParms), ADDCC(TPM2_CC_Commit), ADDCC(TPM2_CC_PolicyPassword), ADDCC(TPM2_CC_ZGen_2Phase), ADDCC(TPM2_CC_EC_Ephemeral), ADDCC(TPM2_CC_PolicyNvWritten), ADDCC(TPM2_CC_PolicyTemplate), ADDCC(TPM2_CC_CreateLoaded), ADDCC(TPM2_CC_PolicyAuthorizeNV), ADDCC(TPM2_CC_EncryptDecrypt2), ADDCC(TPM2_CC_AC_GetCapability), ADDCC(TPM2_CC_AC_Send), ADDCC(TPM2_CC_Policy_AC_SendSelect), ADDCC(TPM2_CC_Vendor_TCG_Test), }; static void test_tpm2_cc_util_from_str_validate_map(void **state) { UNUSED(state); size_t i; for (i = 0; i < ARRAY_LEN(_g_map); i++) { const cc_map *m = &_g_map[i]; TPM2_CC expected = m->cc; TPM2_CC got = 0; bool result = tpm2_cc_util_from_str(m->str, &got); assert_true(result); assert_int_equal(got, expected); const char *sgot = tpm2_cc_util_to_str(m->cc); assert_string_equal(sgot, m->str); } } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); const struct CMUnitTest tests[] = { cmocka_unit_test(test_tpm2_cc_util_from_str_null_str_ptr), cmocka_unit_test(test_tpm2_cc_util_from_str_null_cc_ptr), cmocka_unit_test(test_tpm2_cc_util_from_str_null_ptrs), cmocka_unit_test(test_tpm2_cc_util_from_str_invalid_str), cmocka_unit_test(test_tpm2_cc_util_from_str_empty_str), cmocka_unit_test(test_tpm2_cc_util_from_str_valid_hex_str), cmocka_unit_test(test_tpm2_cc_util_to_str_unknown), cmocka_unit_test(test_tpm2_cc_util_from_str_validate_map), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_files.c000066400000000000000000000157711412464516500176660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include "files.h" typedef struct test_file test_file; struct test_file { char *path; FILE *file; }; static test_file *test_file_new(void) { test_file *tf = malloc(sizeof(test_file)); if (!tf) { return NULL; } tf->path = strdup("xxx_test_files_xxx.test"); if (!tf->path) { free(tf); return NULL; } tf->file = fopen(tf->path, "w+b"); if (!tf->file) { free(tf->path); free(tf); return NULL; } return tf; } static void test_file_free(test_file *tf) { assert_non_null(tf); int rc = remove(tf->path); assert_return_code(rc, errno); free(tf->path); fclose(tf->file); free(tf); } static int test_setup(void **state) { test_file *tf = test_file_new(); assert_non_null(tf); *state = tf; return 0; } static int test_teardown(void **state) { test_file *tf = (test_file *) *state; test_file_free(tf); return 0; } static test_file *test_file_from_state(void **state) { test_file *f = (test_file *) *state; assert_non_null(f); return f; } #define READ_WRITE_TEST(size, expected) \ static void test_file_read_write_##size(void **state) { \ \ FILE *f = test_file_from_state(state)->file; \ \ bool res = files_write_##size(f, expected); \ assert_true(res); \ \ rewind(f); \ \ UINT##size found; \ res = files_read_##size(f, &found); \ assert_true(res); \ \ assert_int_equal(found, expected); \ } READ_WRITE_TEST(16, 0xABCD) READ_WRITE_TEST(32, 0x11223344) READ_WRITE_TEST(64, 0x1122334455667788) static void test_file_read_write_bytes(void **state) { FILE *f = test_file_from_state(state)->file; UINT8 expected[1024]; memset(expected, 0xBB, sizeof(expected)); bool res = files_write_bytes(f, expected, sizeof(expected)); assert_true(res); rewind(f); UINT8 found[1024] = { 0 }; res = files_read_bytes(f, found, sizeof(found)); assert_true(res); assert_memory_equal(expected, found, sizeof(found)); } static void test_file_read_write_0_bytes(void **state) { FILE *f = test_file_from_state(state)->file; UINT8 data[1]; bool res = files_write_bytes(f, data, 0); assert_true(res); res = files_read_bytes(f, data, 0); assert_true(res); } static void test_file_read_write_header(void **state) { FILE *f = test_file_from_state(state)->file; UINT32 expected = 0xAABBCCDD; bool res = files_write_header(f, expected); assert_true(res); rewind(f); UINT32 found; res = files_read_header(f, &found); assert_true(res); assert_int_equal(expected, found); } #define READ_WRITE_TEST_BAD_PARAMS(size) \ static void test_file_read_write_bad_params_##size(void **state) { \ \ UINT##size expected = 42; \ FILE *f = test_file_from_state(state)->file; \ bool res = files_write_##size(NULL, expected); \ assert_false(res); \ \ UINT##size found; \ res = files_read_##size(NULL, &found); \ assert_false(res); \ \ res = files_read_##size(f, NULL); \ assert_false(res); \ \ res = files_read_##size(NULL, NULL); \ assert_false(res); \ } READ_WRITE_TEST_BAD_PARAMS(16) READ_WRITE_TEST_BAD_PARAMS(32) READ_WRITE_TEST_BAD_PARAMS(64) static void test_file_read_write_bad_params_bytes(void **state) { FILE *f = test_file_from_state(state)->file; UINT8 data[1]; bool res = files_write_bytes(f, NULL, sizeof(data)); assert_false(res); res = files_write_bytes(NULL, data, sizeof(data)); assert_false(res); res = files_read_bytes(f, NULL, sizeof(data)); assert_false(res); res = files_read_bytes(NULL, data, sizeof(data)); assert_false(res); } static void test_file_size(void **state) { test_file *tf = test_file_from_state(state); UINT8 data[128] = { 0 }; bool res = files_write_bytes(tf->file, data, sizeof(data)); assert_true(res); int rc = fflush(tf->file); assert_return_code(rc, errno); unsigned long file_size; res = files_get_file_size_path(tf->path, &file_size); assert_true(res); assert_int_equal(file_size, sizeof(data)); } static void test_file_size_bad_args(void **state) { unsigned long file_size; bool res = files_get_file_size_path("this_should_be_a_bad_path", &file_size); assert_false(res); res = files_get_file_size_path(NULL, &file_size); assert_false(res); test_file *tf = test_file_from_state(state); res = files_get_file_size_path(tf->path, NULL); assert_false(res); } static void test_file_exists(void **state) { test_file *tf = test_file_from_state(state); bool res = files_does_file_exist(tf->path); assert_true(res); } static void test_file_exists_bad_args(void **state) { (void) state; bool res = files_does_file_exist("this_should_be_a_bad_path"); assert_false(res); res = files_does_file_exist(NULL); assert_false(res); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(test_file_read_write_16, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_32, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_64, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_bytes, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_0_bytes, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_header, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_bad_params_16, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_bad_params_32, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_bad_params_64, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_read_write_bad_params_bytes, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_size, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_size_bad_args, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_exists, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_file_exists_bad_args, test_setup, test_teardown), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_options.c000066400000000000000000000154011412464516500202450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_options.h" #include "tpm2_util.h" typedef struct test_pair test_pair; struct test_pair { union { const char *cn; void *v; } input[2]; union { char *s; void *v; int i; } output; }; static void set_getenv(const char *name, char *ret) { test_pair *e = calloc(1, sizeof(test_pair)); assert_non_null(e); e->input[0].cn = name; e->output.s = ret; will_return(__wrap_tpm2_util_getenv, e); } #define HANDLE_SKIP_CHECK ((void *) -1) char *__wrap_tpm2_util_getenv(const char *name) { test_pair *x = mock_ptr_type(test_pair *); const char *expected_name = x->input[0].cn; char *ret = x->output.s; free(x); assert_string_equal(name, expected_name); return ret; } TSS2_RC __wrap_Tss2_TctiLdr_Initialize(const char *nameConf, TSS2_TCTI_CONTEXT **context) { UNUSED(nameConf); printf("fml\n"); TSS2_RC rc = mock_type(TSS2_RC); if (rc == TSS2_RC_SUCCESS) { *context = mock_type(TSS2_TCTI_CONTEXT*); } return rc; } static TSS2_TCTI_CONTEXT_COMMON_V2 tcti_instance; static void common_prelude(void) { /* * NULL getenv for the tcti config results * in a default TCTI based on a probe using dlopen(). * * If we find that tcti, we return the tcti conf, which * then results in us following the normal tcti loading logic. */ set_getenv(TPM2TOOLS_ENV_TCTI, NULL); /* mock Tss2_TctiLdr_Initialize */ will_return (__wrap_Tss2_TctiLdr_Initialize, TSS2_RC_SUCCESS); will_return (__wrap_Tss2_TctiLdr_Initialize, &tcti_instance); } static void test_null_tcti_getenv_no_errata(void **state) { UNUSED(state); char *argv[] = { "program", "-Z" // Disable errata getenv call }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; common_prelude(); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_non_null(tcti); assert_int_equal(oc, tpm2_option_code_continue); } static void test_null_tcti_getenv_with_errata(void **state) { UNUSED(state); char *argv[] = { "program", // Enable errata getenv call via no -Z }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; common_prelude(); set_getenv(TPM2TOOLS_ENV_ENABLE_ERRATA, NULL); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_non_null(tcti); assert_int_equal(oc, tpm2_option_code_continue); } static void test_tcti_short_option_no_errata(void **state) { UNUSED(state); char *argv[] = { "program", "-T", // Set TCTI to something specific "tctifake", "-Z" // Disable errata getenv call }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; /* we never call getenv() because we use -T */ /* we never probe for a tcti */ /* we just use what is given, in this case, return a mocked instance */ will_return(__wrap_Tss2_TctiLdr_Initialize, TSS2_RC_SUCCESS); will_return(__wrap_Tss2_TctiLdr_Initialize, &tcti_instance); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_non_null(tcti); assert_int_equal(oc, tpm2_option_code_continue); } static void test_tcti_long_option_with_equals_no_errata(void **state) { UNUSED(state); char *argv[] = { "program", "--tcti=tctifake", // Set TCTI to something specific "-Z" // Disable errata getenv call }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; /* we never call getenv() because we use -T */ /* we never probe for a tcti */ /* we just use what is given, in this case, return a mocked instance */ will_return(__wrap_Tss2_TctiLdr_Initialize, TSS2_RC_SUCCESS); will_return(__wrap_Tss2_TctiLdr_Initialize, &tcti_instance); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_non_null(tcti); assert_int_equal(oc, tpm2_option_code_continue); } static void test_tcti_long_option_no_equals_no_errata(void **state) { UNUSED(state); char *argv[] = { "program", "--tcti", // Set TCTI to something specific "tctifake", "-Z" // Disable errata getenv call }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; /* we never call getenv() because we use -T */ /* we never probe for a tcti */ /* we just use what is given, in this case, return a mocked instance */ will_return(__wrap_Tss2_TctiLdr_Initialize, TSS2_RC_SUCCESS); will_return(__wrap_Tss2_TctiLdr_Initialize, &tcti_instance); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_non_null(tcti); assert_int_equal(oc, tpm2_option_code_continue); } static void test_invalid_tcti_no_errata(void **state) { UNUSED(state); char *argv[] = { "program", "-T", // Set TCTI to something specific "tctiinvalid", "-Z" // Disable errata getenv call }; int argc = ARRAY_LEN(argv); tpm2_options *tool_opts = NULL; tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; will_return(__wrap_Tss2_TctiLdr_Initialize, TSS2_TCTI_RC_NOT_SUPPORTED); tpm2_option_code oc = tpm2_handle_options(argc, argv, tool_opts, &flags, &tcti); assert_int_equal(oc, tpm2_option_code_err); } /* * link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); const struct CMUnitTest tests[] = { cmocka_unit_test(test_null_tcti_getenv_no_errata), cmocka_unit_test(test_null_tcti_getenv_with_errata), cmocka_unit_test(test_tcti_short_option_no_errata), cmocka_unit_test(test_tcti_long_option_no_equals_no_errata), cmocka_unit_test(test_tcti_long_option_with_equals_no_errata), cmocka_unit_test(test_invalid_tcti_no_errata), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_pcr.c000066400000000000000000000046251412464516500173440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "pcr.h" #include "tpm2_util.h" static void test_pcr_alg_nice_names(void **state) { (void) state; TPML_PCR_SELECTION friendly_pcr_selections = TPML_PCR_SELECTION_EMPTY_INIT; bool result = pcr_parse_selections("sha256:16,17,18+0x0b:16,17,18", &friendly_pcr_selections); assert_true(result); TPML_PCR_SELECTION raw_pcr_selections = TPML_PCR_SELECTION_EMPTY_INIT; result = pcr_parse_selections("0xb:16,17,18+0x0b:16,17,18", &raw_pcr_selections); assert_true(result); assert_memory_equal(&friendly_pcr_selections, &raw_pcr_selections, sizeof(raw_pcr_selections)); // select from PCR bank sm3_256 TPML_PCR_SELECTION friendly_pcr_selections_sm3 = TPML_PCR_SELECTION_EMPTY_INIT; bool result_sm3 = pcr_parse_selections("sm3_256:16,17,18+0x12:16,17,18", &friendly_pcr_selections_sm3); assert_true(result_sm3); TPML_PCR_SELECTION raw_pcr_selections_sm3 = TPML_PCR_SELECTION_EMPTY_INIT; result_sm3 = pcr_parse_selections("0x12:16,17,18+0x12:16,17,18", &raw_pcr_selections_sm3); assert_true(result_sm3); assert_memory_equal(&friendly_pcr_selections_sm3, &raw_pcr_selections_sm3, sizeof(raw_pcr_selections_sm3)); // select from PCR bank sha3_256 TPML_PCR_SELECTION friendly_pcr_selections_sha3_256 = TPML_PCR_SELECTION_EMPTY_INIT; bool result_sha3 = pcr_parse_selections("sha3_256:16,17,18+0x27:16,17,18", &friendly_pcr_selections_sha3_256); assert_true(result_sha3); TPML_PCR_SELECTION raw_pcr_selections_sha3_256 = TPML_PCR_SELECTION_EMPTY_INIT; result_sha3 = pcr_parse_selections("0x27:16,17,18+0x27:16,17,18", &raw_pcr_selections_sha3_256); assert_true(result_sha3); assert_memory_equal(&friendly_pcr_selections_sha3_256, &raw_pcr_selections_sha3_256, sizeof(raw_pcr_selections_sha3_256)); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test(test_pcr_alg_nice_names) }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_session_common.h000066400000000000000000000051711412464516500216150ustar00rootroot00000000000000#include "tpm2_alg_util.h" #include "tpm2_util.h" #define SESSION_HANDLE 0xBADC0DE typedef struct expected_data expected_data; struct expected_data { struct { ESYS_TR key; ESYS_TR bind; TPM2_SE session_type; TPMT_SYM_DEF symmetric; TPMI_ALG_HASH auth_hash; TPM2B_NONCE nonce_caller; } input; struct output { ESYS_TR handle; TPM2_RC rc; } output; }; static inline void set_expected(ESYS_TR key, ESYS_TR bind, TPM2_SE session_type, TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH auth_hash, TPM2B_NONCE *nonce_caller, ESYS_TR handle, TPM2_RC rc) { expected_data *e = calloc(1, sizeof(*e)); assert_non_null(e); e->input.key = key; e->input.bind = bind; e->input.session_type = session_type; e->input.symmetric = *symmetric; e->input.auth_hash = auth_hash; if (nonce_caller) { e->input.nonce_caller = *nonce_caller; } e->output.handle = handle; e->output.rc = rc; will_return(__wrap_Esys_StartAuthSession, e); } static inline void set_expected_defaults(TPM2_SE session_type, ESYS_TR handle, TPM2_RC rc) { TPMT_SYM_DEF symmetric; memset(&symmetric, 0, sizeof(symmetric)); symmetric.algorithm = TPM2_ALG_NULL; TPM2B_NONCE nonce_caller; memset(&nonce_caller, 0, sizeof(nonce_caller)); nonce_caller.size = tpm2_alg_util_get_hash_size(TPM2_ALG_SHA1); set_expected( ESYS_TR_NONE, ESYS_TR_NONE, session_type, &symmetric, TPM2_ALG_SHA256, &nonce_caller, handle, rc); } TSS2_RC __wrap_Esys_StartAuthSession(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) { UNUSED(esysContext); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); UNUSED(sessionHandle); expected_data *e = mock_ptr_type(expected_data *); assert_int_equal(tpmKey, e->input.key); assert_int_equal(bind, e->input.bind); if (nonceCaller) { assert_int_equal(e->input.nonce_caller.size, nonceCaller->size); assert_memory_equal(e->input.nonce_caller.buffer, nonceCaller->buffer, nonceCaller->size); } assert_int_equal(sessionType, e->input.session_type); assert_memory_equal(symmetric, &e->input.symmetric, sizeof(*symmetric)); assert_int_equal(authHash, e->input.auth_hash); *sessionHandle = e->output.handle; TSS2_RC rc = e->output.rc; free(e); return rc; } tpm2-tools-5.2/test/unit/test_string_bytes.c000066400000000000000000000056571412464516500213020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_util.h" static void test_is_big_endian(void **state) { uint16_t test = 0xFF00; uint8_t *b = (uint8_t *) &test; (void) state; bool test_host_is_big_endian = b[0] == 0xFF; bool host_is_big_endian = tpm2_util_is_big_endian(); assert_true(test_host_is_big_endian == host_is_big_endian); } static void test_popcount(void **state) { (void) state; UINT32 count = tpm2_util_pop_count(0x4453E424); assert_int_equal(12, count); count = tpm2_util_pop_count(0); assert_int_equal(0, count); count = tpm2_util_pop_count(~0); assert_int_equal(32, count); } #define TEST_ENDIAN_CONVERT(size, value, expected) \ static void test_convert_##size(void **state) { \ \ (void)state; \ UINT##size test = tpm2_util_endian_swap_##size(value); \ assert_int_equal(test, expected); \ } TEST_ENDIAN_CONVERT(16, 0xFF00, 0x00FF) TEST_ENDIAN_CONVERT(32, 0xAABBCCDD, 0xDDCCBBAA) TEST_ENDIAN_CONVERT(64, 0x0011223344556677, 0x7766554433221100) #define TEST_ENDIAN_HTON(size, value, le_expected) \ static void test_hton_##size(void **state) { \ \ (void)state; \ UINT##size test = tpm2_util_hton_##size(value); \ bool is_big_endian = tpm2_util_is_big_endian(); \ UINT##size expected = is_big_endian ? value : le_expected; \ assert_int_equal(test, expected); \ \ } TEST_ENDIAN_HTON(16, 0xFF00, 0x00FF) TEST_ENDIAN_HTON(32, 0xAABBCCDD, 0xDDCCBBAA) TEST_ENDIAN_HTON(64, 0x0011223344556677, 0x7766554433221100) #define TEST_ENDIAN_NTOH(size, value, le_expected) \ static void test_ntoh_##size(void **state) { \ \ (void)state; \ UINT##size test = tpm2_util_ntoh_##size(value); \ bool is_big_endian = tpm2_util_is_big_endian(); \ UINT##size expected = is_big_endian ? value : le_expected; \ assert_int_equal(test, expected); \ \ } TEST_ENDIAN_NTOH(16, 0xFF00, 0x00FF) TEST_ENDIAN_NTOH(32, 0xAABBCCDD, 0xDDCCBBAA) TEST_ENDIAN_NTOH(64, 0x0011223344556677, 0x7766554433221100) /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test(test_is_big_endian), cmocka_unit_test(test_convert_16), cmocka_unit_test(test_convert_32), cmocka_unit_test(test_convert_64), cmocka_unit_test(test_hton_16), cmocka_unit_test(test_hton_32), cmocka_unit_test(test_hton_64), cmocka_unit_test(test_ntoh_16), cmocka_unit_test(test_ntoh_32), cmocka_unit_test(test_ntoh_64), cmocka_unit_test(test_popcount) }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_alg_util.c000066400000000000000000001204631412464516500213210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_util.h" #include "tpm2_alg_util.h" #define xstr(s) str(s) #define str(s) #s #define single_item_test_get(friendly) \ cmocka_unit_test(test_tpm2_alg_util_convert_##friendly) #define nv_single_item_test2(friendly, value, flags) \ static void test_tpm2_alg_util_convert_##friendly(void **state) { \ \ (void)state; \ \ TPM2_ALG_ID found_id = tpm2_alg_util_strtoalg(str(friendly), flags); \ const char *found_str = tpm2_alg_util_algtostr(value, flags); \ char str_value[256]; \ snprintf(str_value, sizeof(str_value), "0x%X", value); \ TPM2_ALG_ID from_hex_str = tpm2_alg_util_from_optarg(str_value, flags); \ TPM2_ALG_ID from_nice_str = tpm2_alg_util_from_optarg(str(friendly), flags); \ \ assert_ptr_not_equal(found_id, NULL); \ assert_string_equal(str(friendly), found_str); \ assert_int_equal(value, found_id); \ assert_int_equal(value, from_hex_str); \ assert_int_equal(value, from_nice_str); \ } #define nv_single_item_test(friendly, value) nv_single_item_test2(friendly, value, tpm2_alg_util_flags_any) nv_single_item_test(rsa, TPM2_ALG_RSA) /* * sha sha1 is it's own test, as alg to string * can return either, based on the map ordering. * */ nv_single_item_test(hmac, TPM2_ALG_HMAC) nv_single_item_test(aes, TPM2_ALG_AES) nv_single_item_test(mgf1, TPM2_ALG_MGF1) nv_single_item_test(keyedhash, TPM2_ALG_KEYEDHASH) nv_single_item_test(xor, TPM2_ALG_XOR) nv_single_item_test(sha256, TPM2_ALG_SHA256) nv_single_item_test(sha384, TPM2_ALG_SHA384) nv_single_item_test(sha512, TPM2_ALG_SHA512) nv_single_item_test(null, TPM2_ALG_NULL) nv_single_item_test(sm3_256, TPM2_ALG_SM3_256) nv_single_item_test(sm4, TPM2_ALG_SM4) nv_single_item_test(rsassa, TPM2_ALG_RSASSA) nv_single_item_test(rsaes, TPM2_ALG_RSAES) nv_single_item_test(rsapss, TPM2_ALG_RSAPSS) nv_single_item_test(oaep, TPM2_ALG_OAEP) nv_single_item_test(ecdsa, TPM2_ALG_ECDSA) nv_single_item_test(ecdh, TPM2_ALG_ECDH) nv_single_item_test(ecdaa, TPM2_ALG_ECDAA) nv_single_item_test(sm2, TPM2_ALG_SM2) nv_single_item_test(ecschnorr, TPM2_ALG_ECSCHNORR) nv_single_item_test(ecmqv, TPM2_ALG_ECMQV) nv_single_item_test(kdf1_sp800_56a, TPM2_ALG_KDF1_SP800_56A) nv_single_item_test(kdf2, TPM2_ALG_KDF2) nv_single_item_test(kdf1_sp800_108, TPM2_ALG_KDF1_SP800_108) nv_single_item_test(ecc, TPM2_ALG_ECC) nv_single_item_test(symcipher, TPM2_ALG_SYMCIPHER) nv_single_item_test(camellia, TPM2_ALG_CAMELLIA) nv_single_item_test(sha3_256, TPM2_ALG_SHA3_256) nv_single_item_test(sha3_384, TPM2_ALG_SHA3_384) nv_single_item_test(sha3_512, TPM2_ALG_SHA3_512) nv_single_item_test(ctr, TPM2_ALG_CTR) nv_single_item_test(ofb, TPM2_ALG_OFB) nv_single_item_test(cbc, TPM2_ALG_CBC) nv_single_item_test(cfb, TPM2_ALG_CFB) nv_single_item_test(ecb, TPM2_ALG_ECB) typedef struct find_unk_data find_unk_data; struct find_unk_data { TPM2_ALG_ID *ids; size_t len; }; static void test_tpm2_alg_util_sha1_test(void **state) { (void) state; TPM2_ALG_ID sha1_found_id = tpm2_alg_util_strtoalg("sha1", tpm2_alg_util_flags_hash); const char *sha1_found_str = tpm2_alg_util_algtostr(TPM2_ALG_SHA1, tpm2_alg_util_flags_hash); char buf[256]; TPM2_ALG_ID sha1_from_hex_str = tpm2_alg_util_from_optarg("sha1", tpm2_alg_util_flags_hash); snprintf(buf, sizeof(buf), "0x%X", TPM2_ALG_SHA1); TPM2_ALG_ID sha1_from_nice_str = tpm2_alg_util_from_optarg(buf, tpm2_alg_util_flags_hash); assert_int_equal(TPM2_ALG_SHA1, sha1_found_id); assert_int_equal(TPM2_ALG_SHA1, sha1_from_hex_str); assert_int_equal(TPM2_ALG_SHA1, sha1_from_nice_str); bool sha1_pass = false; sha1_pass = !strcmp(sha1_found_str, "sha1"); assert_true(sha1_pass); } /* Test the digest specification language */ #define HASH_SHA1 "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" #define HASH_SHA256 "c324d5e9514f00b1a42052666721fb0911090ca197bf831f6568e735bc8522c3" #define HASH_SHA384 "8effdabfe14416214a250f935505250bd991f106065d899db6e19bdc8bf648f3ac0f1935c4f65fe8f798289b1a0d1e06" #define HASH_SHA512 "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6" #define test_digest(digest, expected_hash_str, expected_alg, expected_hash_len) \ do { \ UINT16 _expected_hash_len = expected_hash_len; \ BYTE expected_hash[expected_hash_len]; \ int rc = tpm2_util_hex_to_byte_structure(expected_hash_str, &_expected_hash_len, expected_hash); \ assert_true(rc == 0); \ \ assert_int_equal(digest->hashAlg, expected_alg); \ assert_memory_equal((BYTE *)&digest->digest, expected_hash, \ expected_hash_len); \ } while (0) #define test_digest_sha1(digest) test_digest(digest, HASH_SHA1, TPM2_ALG_SHA1, TPM2_SHA1_DIGEST_SIZE) #define test_digest_sha256(digest) test_digest(digest, HASH_SHA256, TPM2_ALG_SHA256, TPM2_SHA256_DIGEST_SIZE) #define test_digest_sha384(digest) test_digest(digest, HASH_SHA384, TPM2_ALG_SHA384, TPM2_SHA384_DIGEST_SIZE) #define test_digest_sha512(digest) test_digest(digest, HASH_SHA512, TPM2_ALG_SHA512, TPM2_SHA512_DIGEST_SIZE) #define get_single_digest_pcr_parse_test(friendly_hash) \ cmocka_unit_test(test_pcr_parse_digest_list_##friendly_hash) #define add_single_digest_pcr_parse_test(pcrindex, friendly_hash, hash_value, hash_id, hash_size) \ static void test_pcr_parse_digest_list_##friendly_hash(void **state) { \ (void) state; \ \ char mutable_1[] = str(pcrindex)":"str(friendly_hash)"="hash_value; \ tpm2_pcr_digest_spec digest_spec[1]; \ char *optstr[1] = { \ mutable_1 \ }; \ \ bool res = pcr_parse_digest_list(optstr, 1, digest_spec); \ assert_true(res); \ \ TPMT_HA *digest = &digest_spec->digests.digests[0]; \ test_digest(digest, hash_value, hash_id, hash_size); \ } add_single_digest_pcr_parse_test(4, sha1, HASH_SHA1, TPM2_ALG_SHA1, TPM2_SHA1_DIGEST_SIZE) add_single_digest_pcr_parse_test(9, sha256, HASH_SHA256, TPM2_ALG_SHA256, TPM2_SHA256_DIGEST_SIZE) add_single_digest_pcr_parse_test(6, sha384, HASH_SHA384, TPM2_ALG_SHA384, TPM2_SHA384_DIGEST_SIZE) add_single_digest_pcr_parse_test(21, sha512, HASH_SHA512, TPM2_ALG_SHA512, TPM2_SHA512_DIGEST_SIZE) static void test_pcr_parse_digest_list_many_items(void **state) { (void) state; char mutable_1[] = "12:sha1="HASH_SHA1; char mutable_2[] = "5:sha256="HASH_SHA256; char mutable_3[] = "7:sha512="HASH_SHA512; char *optstr[] = { mutable_1, mutable_2, mutable_3 }; tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)]; bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_true(res); size_t i; for (i = 0; i < ARRAY_LEN(digest_spec); i++) { tpm2_pcr_digest_spec *dspec = &digest_spec[i]; /* each pcr only has 1 alg hash specified */ assert_int_equal(dspec->digests.count, 1); TPMT_HA *digest = &dspec->digests.digests[0]; switch (i) { case 0: assert_int_equal(dspec->pcr_index, 12); test_digest_sha1(digest); break; case 1: assert_int_equal(dspec->pcr_index, 5); test_digest_sha256(digest); break; case 2: assert_int_equal(dspec->pcr_index, 7); test_digest_sha512(digest); break; default: fail_msg("Missing algorithm test for: %s", optstr[i]); } } } static void test_pcr_parse_digest_list_compound(void **state) { (void) state; char mutable_1[] = "12:sha1="HASH_SHA1",sha256="HASH_SHA256",sha512="HASH_SHA512; char *optstr[] = { mutable_1, }; tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)]; bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_true(res); tpm2_pcr_digest_spec *dspec = &digest_spec[0]; assert_int_equal(12, dspec->pcr_index); assert_int_equal(3, dspec->digests.count); size_t i; for (i = 0; i < dspec->digests.count && i < TPM2_NUM_PCR_BANKS; i++) { TPMT_HA *digest = &dspec->digests.digests[i]; switch (i) { case 0: test_digest_sha1(digest); break; case 1: test_digest_sha256(digest); break; case 2: test_digest_sha512(digest); break; default: fail_msg("Missing algorithm test for: %u", digest->hashAlg); } } } static void test_pcr_parse_digest_list_bad(void **state) { (void) state; char mutable_1[] = "12"; char *optstr[] = { mutable_1, }; tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)]; bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_2[] = "12:sha256"; optstr[0] = mutable_2; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_3[] = "12:sha256="; optstr[0] = mutable_3; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_4[] = "12:sha256="HASH_SHA1; optstr[0] = mutable_4; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_5[] = "12:sha256="HASH_SHA512; optstr[0] = mutable_5; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_6[] = "12:"; optstr[0] = mutable_6; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); } static void test_pcr_parse_digest_list_bad_alg(void **state) { (void) state; char mutable_1[] = "12"; char *optstr[] = { mutable_1, }; tpm2_pcr_digest_spec digest_spec[ARRAY_LEN(optstr)]; bool res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); char mutable_2[] = "12:rsa="HASH_SHA1; optstr[0] = mutable_2; res = pcr_parse_digest_list(optstr, ARRAY_LEN(digest_spec), digest_spec); assert_false(res); } static void test_tpm2_alg_util_get_hash_size(void **state) { (void) state; UINT16 hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_SHA1); assert_int_equal(hsize, TPM2_SHA1_DIGEST_SIZE); hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_SHA256); assert_int_equal(hsize, TPM2_SHA256_DIGEST_SIZE); hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_SHA384); assert_int_equal(hsize, TPM2_SHA384_DIGEST_SIZE); hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_SHA512); assert_int_equal(hsize, TPM2_SHA512_DIGEST_SIZE); hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_SM3_256); assert_int_equal(hsize, TPM2_SM3_256_DIGEST_SIZE); hsize = tpm2_alg_util_get_hash_size(TPM2_ALG_RSA); assert_int_equal(hsize, 0); } static void test_tpm2_alg_util_flags_sig(void **state) { UNUSED(state); TPM2_ALG_ID good_algs[] = { TPM2_ALG_RSASSA, TPM2_ALG_RSAPSS, TPM2_ALG_HMAC, }; size_t i; for (i = 0; i < ARRAY_LEN(good_algs); i++) { TPM2_ALG_ID id = good_algs[i]; const char *name = tpm2_alg_util_algtostr(id, tpm2_alg_util_flags_sig); assert_non_null(name); } const char *name = tpm2_alg_util_algtostr(TPM2_ALG_AES, tpm2_alg_util_flags_sig); assert_null(name); } static void test_tpm2_alg_util_flags_enc_scheme(void **state) { UNUSED(state); TPM2_ALG_ID good_algs[] = { TPM2_ALG_RSAES, TPM2_ALG_OAEP, }; size_t i; for (i = 0; i < ARRAY_LEN(good_algs); i++) { TPM2_ALG_ID id = good_algs[i]; const char *name = tpm2_alg_util_algtostr(id, tpm2_alg_util_flags_enc_scheme); assert_non_null(name); } const char *name = tpm2_alg_util_algtostr(TPM2_ALG_AES, tpm2_alg_util_flags_enc_scheme); assert_null(name); } static void test_tpm2_alg_util_flags_hash(void **state) { UNUSED(state); TPM2_ALG_ID good_algs[] = { TPM2_ALG_SHA1, TPM2_ALG_SHA256, TPM2_ALG_SHA384, TPM2_ALG_SHA512, TPM2_ALG_SM3_256 }; size_t i; for (i = 0; i < ARRAY_LEN(good_algs); i++) { TPM2_ALG_ID id = good_algs[i]; const char *name = tpm2_alg_util_algtostr(id, tpm2_alg_util_flags_hash); assert_non_null(name); } const char *name = tpm2_alg_util_algtostr(TPM2_ALG_AES, tpm2_alg_util_flags_hash); assert_null(name); } static void test_extended_alg_rsa2048_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa2048", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_NULL); } static void test_extended_alg_rsa2048_aes128cfb_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa2048:aes128cfb", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_NULL); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.sym, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_rsa2048_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("rsa2048", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_NULL); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.sym, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_rsa_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_NULL); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->algorithm, TPM2_ALG_NULL); } static void test_extended_alg_rsa1024_rsaes_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("rsa1024:rsaes", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 1024); assert_int_equal(r->scheme.scheme, TPM2_ALG_RSAES); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.sym, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_rsa1024_rsaes(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa1024:rsaes", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 1024); assert_int_equal(r->scheme.scheme, TPM2_ALG_RSAES); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->algorithm, TPM2_ALG_NULL); } static void test_extended_alg_rsa_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("rsa", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_NULL); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.aes, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_rsa_rsapss(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa:rsapss", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_RSAPSS); TPMT_SYM_DEF_OBJECT *s = &r->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.aes, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_rsa_rsassa_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa:rsassa", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); TPMS_RSA_PARMS *r = &pub.publicArea.parameters.rsaDetail; assert_int_equal(r->exponent, 0); assert_int_equal(r->keyBits, 2048); assert_int_equal(r->scheme.scheme, TPM2_ALG_RSASSA); TPMS_SIG_SCHEME_RSASSA *s = &r->scheme.details.rsassa; assert_int_equal(s->hashAlg, TPM2_ALG_SHA256); } static void test_extended_alg_ecc256_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("ecc256", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_NULL); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); } static void test_extended_alg_ecc256_aes128cbc_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("ecc256:aes128cbc", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_NULL); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); TPMT_SYM_DEF_OBJECT *s = &e->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.sym, TPM2_ALG_CBC); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_ecc384_ecdaa4_sha256_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("ecc384:ecdaa4-sha256", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); assert_int_equal(pub.publicArea.objectAttributes, 0); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_ECDAA); assert_int_equal(e->curveID, TPM2_ECC_NIST_P384); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); TPMS_SIG_SCHEME_ECDAA *a = &e->scheme.details.ecdaa; assert_int_equal(a->count, 4); assert_int_equal(a->hashAlg, TPM2_ALG_SHA256); } static void test_extended_alg_ecc384_ecdaa4_sha256(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("ecc384:ecdaa4-sha256", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_ECDAA); assert_int_equal(e->curveID, TPM2_ECC_NIST_P384); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); TPMS_SIG_SCHEME_ECDAA *a = &e->scheme.details.ecdaa; assert_int_equal(a->count, 4); assert_int_equal(a->hashAlg, TPM2_ALG_SHA256); TPMT_SYM_DEF_OBJECT *s = &e->symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.sym, TPM2_ALG_CFB); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_ecc256_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("ecc256", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_NULL); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); } static void test_extended_alg_ecc_non_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("ecc", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_NULL); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); } static void test_extended_alg_ecc_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("ecc", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_NULL); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); } static void test_extended_alg_ecc_ecdsa_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("ecc:ecdaa", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_ECC); TPMS_ECC_PARMS *e = &pub.publicArea.parameters.eccDetail; assert_int_equal(e->scheme.scheme, TPM2_ALG_ECDAA); assert_int_equal(e->curveID, TPM2_ECC_NIST_P256); assert_int_equal(e->kdf.scheme, TPM2_ALG_NULL); assert_int_equal(e->kdf.details.mgf1.hashAlg, 0); TPMS_SIG_SCHEME_ECDAA *a = &e->scheme.details.ecdaa; assert_int_equal(a->count, 0); assert_int_equal(a->hashAlg, TPM2_ALG_SHA256); } static void test_extended_alg_xor_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("xor", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMT_KEYEDHASH_SCHEME *s = &pub.publicArea.parameters.keyedHashDetail.scheme; assert_int_equal(s->scheme, TPM2_ALG_XOR); assert_int_equal(s->details.exclusiveOr.hashAlg, TPM2_ALG_SHA256); assert_int_equal(s->details.exclusiveOr.kdf, TPM2_ALG_KDF1_SP800_108); } static void test_extended_alg_xorsha256_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("xor:sha256", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMT_KEYEDHASH_SCHEME *s = &pub.publicArea.parameters.keyedHashDetail.scheme; assert_int_equal(s->scheme, TPM2_ALG_XOR); assert_int_equal(s->details.exclusiveOr.hashAlg, TPM2_ALG_SHA256); assert_int_equal(s->details.exclusiveOr.kdf, TPM2_ALG_KDF1_SP800_108); } static void test_extended_alg_xor(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("xor", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMT_KEYEDHASH_SCHEME *s = &pub.publicArea.parameters.keyedHashDetail.scheme; assert_int_equal(s->scheme, TPM2_ALG_XOR); assert_int_equal(s->details.exclusiveOr.hashAlg, TPM2_ALG_SHA256); assert_int_equal(s->details.exclusiveOr.kdf, TPM2_ALG_KDF1_SP800_108); } static void test_extended_alg_xorsha256(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("xor:sha256", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMT_KEYEDHASH_SCHEME *s = &pub.publicArea.parameters.keyedHashDetail.scheme; assert_int_equal(s->scheme, TPM2_ALG_XOR); assert_int_equal(s->details.exclusiveOr.hashAlg, TPM2_ALG_SHA256); assert_int_equal(s->details.exclusiveOr.kdf, TPM2_ALG_KDF1_SP800_108); } static void test_extended_alg_hmac_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("hmac", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMI_ALG_HASH alg = pub.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg; assert_int_equal(alg, TPM2_ALG_SHA256); } static void test_extended_alg_hmac(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("hmac", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMI_ALG_HASH alg = pub.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg; assert_int_equal(alg, TPM2_ALG_SHA256); } static void test_extended_alg_hmacsha384_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("hmac:sha384", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, TPMA_OBJECT_RESTRICTED); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMI_ALG_HASH alg = pub.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg; assert_int_equal(alg, TPM2_ALG_SHA384); } static void test_extended_alg_hmacsha384(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("hmac:sha384", &pub); assert_true(res); assert_int_equal(pub.publicArea.objectAttributes, 0); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMI_ALG_HASH alg = pub.publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg; assert_int_equal(alg, TPM2_ALG_SHA384); } static void test_extended_alg_aes_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.aes, TPM2_ALG_NULL); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_aes(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.aes, TPM2_ALG_NULL); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_aes256_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes256", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 256); assert_int_equal(s->mode.aes, TPM2_ALG_NULL); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_aes256(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes256", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 256); assert_int_equal(s->mode.aes, TPM2_ALG_NULL); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_aes256cbc_restricted(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes256cbc", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 256); assert_int_equal(s->mode.aes, TPM2_ALG_CBC); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_aes256cbc(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { .publicArea = { .objectAttributes = TPMA_OBJECT_RESTRICTED } }; bool res = tpm2_alg_util_handle_ext_alg("aes256cbc", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 256); assert_int_equal(s->mode.aes, TPM2_ALG_CBC); assert_int_equal(s->algorithm, TPM2_ALG_AES); } static void test_extended_alg_keyedhash(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("keyedhash", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_KEYEDHASH); TPMS_KEYEDHASH_PARMS *k = &pub.publicArea.parameters.keyedHashDetail; assert_int_equal(k->scheme.scheme, TPM2_ALG_NULL); } static void test_extended_rsa_camellia(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa:camellia", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.rsaDetail.symmetric; assert_int_equal(s->keyBits.aes, 128); assert_int_equal(s->mode.aes, TPM2_ALG_NULL); assert_int_equal(s->algorithm, TPM2_ALG_CAMELLIA); } static void test_extended_rsa_camellia256cbc(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("rsa:camellia256cbc", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_RSA); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.rsaDetail.symmetric; assert_int_equal(s->keyBits.aes, 256); assert_int_equal(s->mode.aes, TPM2_ALG_CBC); assert_int_equal(s->algorithm, TPM2_ALG_CAMELLIA); } static void test_extended_camellia192cbc(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("camellia192cbc", &pub); assert_true(res); assert_int_equal(pub.publicArea.type, TPM2_ALG_SYMCIPHER); TPMT_SYM_DEF_OBJECT *s = &pub.publicArea.parameters.symDetail.sym; assert_int_equal(s->keyBits.aes, 192); assert_int_equal(s->mode.aes, TPM2_ALG_CBC); assert_int_equal(s->algorithm, TPM2_ALG_CAMELLIA); } static void test_extended_alg_bad(void **state) { UNUSED(state); TPM2B_PUBLIC pub = { 0 }; bool res = tpm2_alg_util_handle_ext_alg("ecc256funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("ecc256:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("rsafunnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("rsa:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("rsa2048funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("rsa2048:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("aesfunnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("aes:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("aes128funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("aes128:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("xorfunnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("xor:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("hmacfunnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("hmac:funnytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("keyedhashfunytexthere", &pub); assert_false(res); res = tpm2_alg_util_handle_ext_alg("keyedhash:funnytexthere", &pub); assert_false(res); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { single_item_test_get(rsa), cmocka_unit_test(test_tpm2_alg_util_sha1_test), single_item_test_get(hmac), single_item_test_get(aes), single_item_test_get(mgf1), single_item_test_get(keyedhash), single_item_test_get(xor), single_item_test_get(sha256), single_item_test_get(sha384), single_item_test_get(sha512), single_item_test_get(null), single_item_test_get(sm3_256), single_item_test_get(sm4), single_item_test_get(rsassa), single_item_test_get(rsaes), single_item_test_get(rsapss), single_item_test_get(oaep), single_item_test_get(ecdsa), single_item_test_get(ecdh), single_item_test_get(ecdaa), single_item_test_get(sm2), single_item_test_get(ecschnorr), single_item_test_get(ecmqv), single_item_test_get(kdf1_sp800_56a), single_item_test_get(kdf2), single_item_test_get(kdf1_sp800_108), single_item_test_get(ecc), single_item_test_get(symcipher), single_item_test_get(camellia), single_item_test_get(sha3_256), single_item_test_get(sha3_384), single_item_test_get(sha3_512), single_item_test_get(ctr), single_item_test_get(ofb), single_item_test_get(cbc), single_item_test_get(cfb), single_item_test_get(ecb), get_single_digest_pcr_parse_test(sha1), get_single_digest_pcr_parse_test(sha256), get_single_digest_pcr_parse_test(sha384), get_single_digest_pcr_parse_test(sha512), cmocka_unit_test(test_pcr_parse_digest_list_many_items), cmocka_unit_test(test_pcr_parse_digest_list_compound), cmocka_unit_test(test_pcr_parse_digest_list_bad), cmocka_unit_test(test_pcr_parse_digest_list_bad_alg), cmocka_unit_test(test_tpm2_alg_util_get_hash_size), cmocka_unit_test(test_tpm2_alg_util_flags_sig), cmocka_unit_test(test_tpm2_alg_util_flags_enc_scheme), cmocka_unit_test(test_tpm2_alg_util_flags_hash), cmocka_unit_test(test_extended_alg_rsa2048_non_restricted), cmocka_unit_test(test_extended_alg_rsa2048_restricted), cmocka_unit_test(test_extended_alg_rsa_non_restricted), cmocka_unit_test(test_extended_alg_rsa_restricted), cmocka_unit_test(test_extended_alg_rsa1024_rsaes_restricted), cmocka_unit_test(test_extended_alg_rsa1024_rsaes), cmocka_unit_test(test_extended_alg_rsa_rsapss), cmocka_unit_test(test_extended_alg_rsa_rsassa_non_restricted), cmocka_unit_test(test_extended_alg_rsa2048_aes128cfb_non_restricted), cmocka_unit_test(test_extended_alg_ecc256_non_restricted), cmocka_unit_test(test_extended_alg_ecc256_aes128cbc_non_restricted), cmocka_unit_test(test_extended_alg_ecc384_ecdaa4_sha256_non_restricted), cmocka_unit_test(test_extended_alg_ecc384_ecdaa4_sha256), cmocka_unit_test(test_extended_alg_ecc256_restricted), cmocka_unit_test(test_extended_alg_ecc_non_restricted), cmocka_unit_test(test_extended_alg_ecc_restricted), cmocka_unit_test(test_extended_alg_ecc_ecdsa_restricted), cmocka_unit_test(test_extended_alg_xor_restricted), cmocka_unit_test(test_extended_alg_xor), cmocka_unit_test(test_extended_alg_xorsha256_restricted), cmocka_unit_test(test_extended_alg_xorsha256), cmocka_unit_test(test_extended_alg_hmac_restricted), cmocka_unit_test(test_extended_alg_hmac), cmocka_unit_test(test_extended_alg_hmacsha384_restricted), cmocka_unit_test(test_extended_alg_hmacsha384), cmocka_unit_test(test_extended_alg_aes_restricted), cmocka_unit_test(test_extended_alg_aes), cmocka_unit_test(test_extended_alg_aes256_restricted), cmocka_unit_test(test_extended_alg_aes256), cmocka_unit_test(test_extended_alg_aes256cbc_restricted), cmocka_unit_test(test_extended_alg_aes256cbc), cmocka_unit_test(test_extended_alg_keyedhash), cmocka_unit_test(test_extended_rsa_camellia), cmocka_unit_test(test_extended_rsa_camellia256cbc), cmocka_unit_test(test_extended_camellia192cbc), cmocka_unit_test(test_extended_alg_bad), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_attr_util.c000066400000000000000000000442131412464516500215260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_attr_util.h" #define test_nv_strtoattr_get(set) \ cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_##set) #define nv_single_item_test(argstr, set) \ static void test_tpm2_attr_util_nv_strtoattr_##set(void **state) { \ \ (void)state; \ \ TPMA_NV nvattrs = 0; \ /* make mutable strings for strtok_r */ \ char arg[] = argstr; \ bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); \ assert_true(res); \ assert_true(nvattrs == set); \ } nv_single_item_test("authread", TPMA_NV_AUTHREAD); nv_single_item_test("authwrite", TPMA_NV_AUTHWRITE); nv_single_item_test("clear_stclear", TPMA_NV_CLEAR_STCLEAR); nv_single_item_test("globallock", TPMA_NV_GLOBALLOCK); nv_single_item_test("no_da", TPMA_NV_NO_DA); nv_single_item_test("orderly", TPMA_NV_ORDERLY); nv_single_item_test("ownerread", TPMA_NV_OWNERREAD); nv_single_item_test("ownerwrite", TPMA_NV_OWNERWRITE); nv_single_item_test("platformcreate", TPMA_NV_PLATFORMCREATE); nv_single_item_test("policyread", TPMA_NV_POLICYREAD); nv_single_item_test("policywrite", TPMA_NV_POLICYWRITE); nv_single_item_test("policydelete", TPMA_NV_POLICY_DELETE); nv_single_item_test("ppread", TPMA_NV_PPREAD); nv_single_item_test("ppwrite", TPMA_NV_PPWRITE); nv_single_item_test("readlocked", TPMA_NV_READLOCKED); nv_single_item_test("read_stclear", TPMA_NV_READ_STCLEAR); nv_single_item_test("writeall", TPMA_NV_WRITEALL); nv_single_item_test("writedefine", TPMA_NV_WRITEDEFINE); nv_single_item_test("writelocked", TPMA_NV_WRITELOCKED); nv_single_item_test("write_stclear", TPMA_NV_WRITE_STCLEAR); nv_single_item_test("written", TPMA_NV_WRITTEN); static void test_tpm2_attr_util_nv_strtoattr_nt_good(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "nt=0x1"; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_true(res); assert_true((nvattrs & TPMA_NV_TPM2_NT_MASK) >> TPMA_NV_TPM2_NT_SHIFT == 0x1); } static void test_tpm2_attr_util_nv_strtoattr_nt_bad(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "nt=16"; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_false(res); } static void test_tpm2_attr_util_nv_strtoattr_nt_malformed(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "nt="; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_false(res); char arg1[] = "nt"; res = tpm2_attr_util_nv_strtoattr(arg1, &nvattrs); assert_false(res); } static void test_tpm2_attr_util_nv_strtoattr_option_no_option(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "authread="; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_false(res); char arg1[] = "authread=0x1"; res = tpm2_attr_util_nv_strtoattr(arg1, &nvattrs); assert_false(res); } static void test_tpm2_attr_util_nv_strtoattr_multiple_good(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "authread|authwrite|nt=0x4"; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_true(res); assert_true((nvattrs & TPMA_NV_TPM2_NT_MASK) >> TPMA_NV_TPM2_NT_SHIFT == 0x4); assert_true(nvattrs & TPMA_NV_AUTHREAD); assert_true(nvattrs & TPMA_NV_AUTHWRITE); } static void test_tpm2_attr_util_nv_strtoattr_token_unknown(void **state) { (void) state; TPMA_NV nvattrs = 0; char arg[] = "authread|authfoo|nt=0x4"; bool res = tpm2_attr_util_nv_strtoattr(arg, &nvattrs); assert_false(res); char arg1[] = "foo"; res = tpm2_attr_util_nv_strtoattr(arg1, &nvattrs); assert_false(res); char arg2[] = "foo="; res = tpm2_attr_util_nv_strtoattr(arg2, &nvattrs); assert_false(res); /* should be interpreted as the whole thing, no = */ char arg3[] = "nt:0x4"; res = tpm2_attr_util_nv_strtoattr(arg3, &nvattrs); assert_false(res); } #define test_nv_attrtostr(value, expected) \ static void test_tpm2_nv_util_attrtostr_##value(void **state) { \ \ (void) state; \ \ TPMA_NV attrs = value; \ char *str = tpm2_attr_util_nv_attrtostr(attrs); \ assert_string_equal(str, expected); \ \ free(str); \ } #define test_nv_attrtostr_get(value) \ cmocka_unit_test(test_tpm2_nv_util_attrtostr_##value) test_nv_attrtostr(0, ""); test_nv_attrtostr(TPMA_NV_PPWRITE, "ppwrite") test_nv_attrtostr(TPMA_NV_OWNERWRITE, "ownerwrite") test_nv_attrtostr(TPMA_NV_AUTHWRITE, "authwrite") test_nv_attrtostr(TPMA_NV_POLICYWRITE, "policywrite") test_nv_attrtostr(TPMA_NV_POLICY_DELETE, "policydelete") test_nv_attrtostr(TPMA_NV_WRITELOCKED, "writelocked") test_nv_attrtostr(TPMA_NV_WRITEALL, "writeall") test_nv_attrtostr(TPMA_NV_WRITEDEFINE, "writedefine") test_nv_attrtostr(TPMA_NV_WRITE_STCLEAR, "write_stclear") test_nv_attrtostr(TPMA_NV_GLOBALLOCK, "globallock") test_nv_attrtostr(TPMA_NV_PPREAD, "ppread") test_nv_attrtostr(TPMA_NV_OWNERREAD, "ownerread") test_nv_attrtostr(TPMA_NV_AUTHREAD, "authread") test_nv_attrtostr(TPMA_NV_POLICYREAD, "policyread") test_nv_attrtostr(TPMA_NV_NO_DA, "no_da") test_nv_attrtostr(TPMA_NV_ORDERLY, "orderly") test_nv_attrtostr(TPMA_NV_CLEAR_STCLEAR, "clear_stclear") test_nv_attrtostr(TPMA_NV_READLOCKED, "readlocked") test_nv_attrtostr(TPMA_NV_WRITTEN, "written") test_nv_attrtostr(TPMA_NV_PLATFORMCREATE, "platformcreate") test_nv_attrtostr(TPMA_NV_READ_STCLEAR, "read_stclear") test_nv_attrtostr(0x100, "") //bit 8 - reserved test_nv_attrtostr(0x200, "") //bit 9 - reserved test_nv_attrtostr(0x100000, "") //bit 20 - reserved test_nv_attrtostr(0x200000, "") //bit 21 - reserved test_nv_attrtostr(0x400000, "") //bit 22 - reserved test_nv_attrtostr(0x800000, "") //bit 23- reserved test_nv_attrtostr(0x1000000, "") //bit 24- reserved test_nv_attrtostr(0x30, "nt=0x3") //bit 24- reserved test_nv_attrtostr(0x90, "nt=0x9") //bit 24- reserved #define NV_ALL_FIELDS \ "ppwrite|ownerwrite|authwrite|policywrite|nt=0xF|" \ "||policydelete|writelocked|writeall|writedefine" \ "|write_stclear|globallock|ppread|ownerread|authread|policyread" \ "||||" \ "||no_da|orderly|clear_stclear|readlocked|written" \ "|platformcreate|read_stclear" test_nv_attrtostr(0xFFFFFFFF, NV_ALL_FIELDS); #define test_nv_attrtostr_compound(id, value, expected) \ static void test_tpm2_nv_util_attrtostr_##id(void **state) { \ \ (void) state; \ \ TPMA_NV attrs = value; \ char *str = tpm2_attr_util_nv_attrtostr(attrs); \ assert_string_equal(str, expected); \ \ free(str); \ } test_nv_attrtostr_compound(stclear_ppwrite, TPMA_NV_WRITE_STCLEAR | TPMA_NV_PPWRITE, "ppwrite|write_stclear") test_nv_attrtostr_compound(stclear_ppwrite_0x30, TPMA_NV_WRITE_STCLEAR | TPMA_NV_PPWRITE | 0x30, "ppwrite|nt=0x3|write_stclear") test_nv_attrtostr_compound(platformcreate_ownerread_nt_0x90_0x20000, TPMA_NV_PLATFORMCREATE | TPMA_NV_AUTHWRITE | 0x90 | 0x200000, "authwrite|nt=0x9||platformcreate") /* * TPMA_OBJECT Tests */ #define obj_single_item_test(argstr, set) \ static void test_tpm2_attr_util_nv_strtoattr_##set(void **state) { \ \ (void)state; \ \ TPMA_OBJECT objattrs = 0; \ /* make mutable strings for strtok_r */ \ char arg[] = argstr; \ bool res = tpm2_attr_util_obj_strtoattr(arg, &objattrs); \ assert_true(res); \ assert_true(objattrs & set); \ } #define test_obj_strtoattr_get(set) \ cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_##set) obj_single_item_test("fixedtpm", TPMA_OBJECT_FIXEDTPM); obj_single_item_test("stclear", TPMA_OBJECT_STCLEAR); obj_single_item_test("fixedparent", TPMA_OBJECT_FIXEDPARENT); obj_single_item_test("sensitivedataorigin", TPMA_OBJECT_SENSITIVEDATAORIGIN); obj_single_item_test("userwithauth", TPMA_OBJECT_USERWITHAUTH); obj_single_item_test("adminwithpolicy", TPMA_OBJECT_ADMINWITHPOLICY); obj_single_item_test("noda", TPMA_OBJECT_NODA); obj_single_item_test("encryptedduplication", TPMA_OBJECT_ENCRYPTEDDUPLICATION); obj_single_item_test("restricted", TPMA_OBJECT_RESTRICTED); obj_single_item_test("decrypt", TPMA_OBJECT_DECRYPT); obj_single_item_test("sign", TPMA_OBJECT_SIGN_ENCRYPT); #define OBJ_ALL_FIELDS \ "|fixedtpm|stclear||fixedparent" \ "|sensitivedataorigin|userwithauth|adminwithpolicy||" \ "|noda|encryptedduplication||" \ "|||restricted|decrypt|" \ "sign|||||" \ "||||" \ "||||" \ "" #define test_obj_attrtostr(value, expected) \ static void test_tpm2_obj_util_attrtostr_##value(void **state) { \ \ (void) state; \ \ TPMA_OBJECT attrs = value; \ char *str = tpm2_attr_util_obj_attrtostr(attrs); \ assert_string_equal(str, expected); \ \ free(str); \ } #define test_obj_attrtostr_get(value) \ cmocka_unit_test(test_tpm2_obj_util_attrtostr_##value) test_obj_attrtostr(0xFFFFFFFF, OBJ_ALL_FIELDS); test_obj_attrtostr(TPMA_OBJECT_FIXEDTPM, "fixedtpm"); test_obj_attrtostr(TPMA_OBJECT_STCLEAR, "stclear"); test_obj_attrtostr(TPMA_OBJECT_FIXEDPARENT, "fixedparent"); test_obj_attrtostr(TPMA_OBJECT_SENSITIVEDATAORIGIN, "sensitivedataorigin"); test_obj_attrtostr(TPMA_OBJECT_USERWITHAUTH, "userwithauth"); test_obj_attrtostr(TPMA_OBJECT_ADMINWITHPOLICY, "adminwithpolicy"); test_obj_attrtostr(TPMA_OBJECT_NODA, "noda"); test_obj_attrtostr(TPMA_OBJECT_ENCRYPTEDDUPLICATION, "encryptedduplication"); test_obj_attrtostr(TPMA_OBJECT_RESTRICTED, "restricted"); test_obj_attrtostr(TPMA_OBJECT_DECRYPT, "decrypt"); test_obj_attrtostr(TPMA_OBJECT_SIGN_ENCRYPT, "sign"); test_obj_attrtostr(TPMA_OBJECT_RESERVED1_MASK, ""); test_obj_attrtostr(TPMA_OBJECT_RESERVED2_MASK, ""); test_obj_attrtostr(TPMA_OBJECT_RESERVED3_MASK, "|"); test_obj_attrtostr(TPMA_OBJECT_RESERVED4_MASK, "||" \ "|"); test_obj_attrtostr(TPMA_OBJECT_RESERVED5_MASK, "||" \ "||||" \ "||||" \ "||"); static void test_tpm2_attr_util_obj_strtoattr_multiple_good(void **state) { (void) state; TPMA_OBJECT objattrs = 0; char arg[] = "sign|adminwithpolicy|noda"; bool res = tpm2_attr_util_obj_strtoattr(arg, &objattrs); assert_true(res); assert_true(objattrs & TPMA_OBJECT_ADMINWITHPOLICY); assert_true(objattrs & TPMA_OBJECT_SIGN_ENCRYPT); assert_true(objattrs & TPMA_OBJECT_NODA); assert_int_equal(objattrs, TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_NODA | TPMA_OBJECT_ADMINWITHPOLICY); } static void test_tpm2_attr_util_obj_strtoattr_token_unknown(void **state) { (void) state; TPMA_OBJECT objattrs = 0; char arg[] = "fixedtpm|noda|unknown"; bool res = tpm2_attr_util_obj_strtoattr(arg, &objattrs); assert_false(res); char arg1[] = "foo"; res = tpm2_attr_util_obj_strtoattr(arg1, &objattrs); assert_false(res); } static void test_tpm2_attr_util_obj_from_optarg_good(void **state) { (void) state; TPMA_OBJECT objattrs = 0; bool res = tpm2_attr_util_obj_from_optarg("0x00000002", &objattrs); assert_true(res); assert_int_equal(0x02, objattrs); objattrs = 0; char buf[] = "fixedtpm"; res = tpm2_attr_util_obj_from_optarg(buf, &objattrs); assert_true(res); assert_int_equal(TPMA_OBJECT_FIXEDTPM, objattrs); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { /* TPMA_NV Tests */ test_nv_strtoattr_get(TPMA_NV_AUTHREAD), test_nv_strtoattr_get(TPMA_NV_AUTHWRITE), test_nv_strtoattr_get(TPMA_NV_CLEAR_STCLEAR), test_nv_strtoattr_get(TPMA_NV_GLOBALLOCK), test_nv_strtoattr_get(TPMA_NV_NO_DA), test_nv_strtoattr_get(TPMA_NV_ORDERLY), test_nv_strtoattr_get(TPMA_NV_OWNERREAD), test_nv_strtoattr_get(TPMA_NV_OWNERWRITE), test_nv_strtoattr_get(TPMA_NV_PLATFORMCREATE), test_nv_strtoattr_get(TPMA_NV_POLICYREAD), test_nv_strtoattr_get(TPMA_NV_POLICYWRITE), test_nv_strtoattr_get(TPMA_NV_POLICY_DELETE), test_nv_strtoattr_get(TPMA_NV_PPREAD), test_nv_strtoattr_get(TPMA_NV_PPWRITE), test_nv_strtoattr_get(TPMA_NV_READLOCKED), test_nv_strtoattr_get(TPMA_NV_READ_STCLEAR), test_nv_strtoattr_get(TPMA_NV_WRITEALL), test_nv_strtoattr_get(TPMA_NV_WRITEDEFINE), test_nv_strtoattr_get(TPMA_NV_WRITELOCKED), test_nv_strtoattr_get(TPMA_NV_WRITE_STCLEAR), test_nv_strtoattr_get(TPMA_NV_WRITTEN), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_nt_good), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_nt_bad), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_nt_malformed), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_multiple_good), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_option_no_option), cmocka_unit_test(test_tpm2_attr_util_nv_strtoattr_token_unknown), test_nv_attrtostr_get(TPMA_NV_PPWRITE), test_nv_attrtostr_get(TPMA_NV_OWNERWRITE), test_nv_attrtostr_get(TPMA_NV_AUTHWRITE), test_nv_attrtostr_get(TPMA_NV_POLICYWRITE), test_nv_attrtostr_get(TPMA_NV_POLICY_DELETE), test_nv_attrtostr_get(TPMA_NV_WRITELOCKED), test_nv_attrtostr_get(TPMA_NV_WRITEALL), test_nv_attrtostr_get(TPMA_NV_WRITEDEFINE), test_nv_attrtostr_get(TPMA_NV_WRITE_STCLEAR), test_nv_attrtostr_get(TPMA_NV_GLOBALLOCK), test_nv_attrtostr_get(TPMA_NV_PPREAD), test_nv_attrtostr_get(TPMA_NV_OWNERREAD), test_nv_attrtostr_get(TPMA_NV_AUTHREAD), test_nv_attrtostr_get(TPMA_NV_POLICYREAD), test_nv_attrtostr_get(TPMA_NV_NO_DA), test_nv_attrtostr_get(TPMA_NV_ORDERLY), test_nv_attrtostr_get(TPMA_NV_CLEAR_STCLEAR), test_nv_attrtostr_get(TPMA_NV_READLOCKED), test_nv_attrtostr_get(TPMA_NV_WRITTEN), test_nv_attrtostr_get(TPMA_NV_PLATFORMCREATE), test_nv_attrtostr_get(TPMA_NV_READ_STCLEAR), test_nv_attrtostr_get(0), test_nv_attrtostr_get(0xFFFFFFFF), test_nv_attrtostr_get(0x100), // bit 8 - reserved test_nv_attrtostr_get(0x200), // bit 9 - reserved test_nv_attrtostr_get(0x100000), //bit 20 - reserved test_nv_attrtostr_get(0x200000), //bit 21 - reserved test_nv_attrtostr_get(0x400000), //bit 22 - reserved test_nv_attrtostr_get(0x800000), //bit 23- reserved test_nv_attrtostr_get(0x1000000), //bit 24- reserved test_nv_attrtostr_get(0x30), //nt=0x3 test_nv_attrtostr_get(0x90), //nt=0x9 test_nv_attrtostr_get(stclear_ppwrite), test_nv_attrtostr_get(stclear_ppwrite_0x30), test_nv_attrtostr_get(platformcreate_ownerread_nt_0x90_0x20000), /* TPMA_OBJECT Tests */ /* From String to Attribute value */ test_obj_strtoattr_get(TPMA_OBJECT_FIXEDTPM), test_obj_strtoattr_get(TPMA_OBJECT_STCLEAR), test_obj_strtoattr_get(TPMA_OBJECT_FIXEDPARENT), test_obj_strtoattr_get(TPMA_OBJECT_SENSITIVEDATAORIGIN), test_obj_strtoattr_get(TPMA_OBJECT_USERWITHAUTH), test_obj_strtoattr_get(TPMA_OBJECT_ADMINWITHPOLICY), test_obj_strtoattr_get(TPMA_OBJECT_NODA), test_obj_strtoattr_get(TPMA_OBJECT_ENCRYPTEDDUPLICATION), test_obj_strtoattr_get(TPMA_OBJECT_RESTRICTED), test_obj_strtoattr_get(TPMA_OBJECT_DECRYPT), test_obj_strtoattr_get(TPMA_OBJECT_ADMINWITHPOLICY), test_obj_strtoattr_get(TPMA_OBJECT_SIGN_ENCRYPT), /* From attribute to string value */ test_obj_attrtostr_get(0xFFFFFFFF), test_obj_attrtostr_get(TPMA_OBJECT_FIXEDTPM), test_obj_attrtostr_get(TPMA_OBJECT_STCLEAR), test_obj_attrtostr_get(TPMA_OBJECT_FIXEDPARENT), test_obj_attrtostr_get(TPMA_OBJECT_SENSITIVEDATAORIGIN), test_obj_attrtostr_get(TPMA_OBJECT_USERWITHAUTH), test_obj_attrtostr_get(TPMA_OBJECT_ADMINWITHPOLICY), test_obj_attrtostr_get(TPMA_OBJECT_NODA), test_obj_attrtostr_get(TPMA_OBJECT_ENCRYPTEDDUPLICATION), test_obj_attrtostr_get(TPMA_OBJECT_RESTRICTED), test_obj_attrtostr_get(TPMA_OBJECT_DECRYPT), test_obj_attrtostr_get(TPMA_OBJECT_SIGN_ENCRYPT), test_obj_attrtostr_get(TPMA_OBJECT_RESERVED1_MASK), test_obj_attrtostr_get(TPMA_OBJECT_RESERVED2_MASK), test_obj_attrtostr_get(TPMA_OBJECT_RESERVED3_MASK), test_obj_attrtostr_get(TPMA_OBJECT_RESERVED4_MASK), test_obj_attrtostr_get(TPMA_OBJECT_RESERVED5_MASK), /* compound good */ cmocka_unit_test(test_tpm2_attr_util_obj_strtoattr_multiple_good), /* negative tests */ cmocka_unit_test(test_tpm2_attr_util_obj_strtoattr_token_unknown), /* test from an optarg */ cmocka_unit_test(test_tpm2_attr_util_obj_from_optarg_good) }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_auth_util.c000066400000000000000000000261701412464516500215170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "tpm2_auth_util.h" #include "tpm2_auth_util.c" /* we want to test the static function parse_pcr */ #include "esys_stubs.h" #include "test_session_common.h" TSS2_RC __wrap_Esys_TR_SetAuth(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_AUTH const *authValue) { UNUSED(esysContext); UNUSED(handle); UNUSED(authValue); return TPM2_RC_SUCCESS; } static void test_tpm2_auth_util_from_optarg_raw_noprefix(void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "abcd", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 4); assert_memory_equal(auth->buffer, "abcd", 4); tpm2_session_close(&session); } static void test_tpm2_auth_util_from_optarg_str_prefix(void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "str:abcd", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 4); assert_memory_equal(auth->buffer, "abcd", 4); tpm2_session_close(&session); } static void test_tpm2_auth_util_from_optarg_hex_prefix(void **state) { (void) state; tpm2_session *session; BYTE expected[] = { 0x12, 0x34, 0xab, 0xcd }; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "hex:1234abcd", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, sizeof(expected)); assert_memory_equal(auth->buffer, expected, sizeof(expected)); tpm2_session_close(&session); } static void test_tpm2_auth_util_from_optarg_str_escaped_hex_prefix( void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "str:hex:1234abcd", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 12); assert_memory_equal(auth->buffer, "hex:1234abcd", 12); tpm2_session_close(&session); } FILE mocked_file_stream; const char *mocked_file_data = "sekretpasswrd"; FILE * __real_fopen(const char *path, const char *mode); FILE * __wrap_fopen(const char *path, const char *mode) { if (strcmp(path, "test_tpm2_auth_util_foobar")) { return __real_fopen(path, mode); } return mock_ptr_type(FILE*); } size_t __real_fread(void *ptr, size_t size, size_t nmemb, FILE *stream); size_t __wrap_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { if (stream != &mocked_file_stream) { return __real_fread(ptr, size, nmemb, stream); } strncpy(ptr, mocked_file_data, size * nmemb); return mock_type(size_t); } long __real_ftell(FILE *stream); long __wrap_ftell(FILE *stream) { if (stream != &mocked_file_stream) { return __real_ftell(stream); } return mock_type(long); } int __real_fseek(FILE *stream, long offset, int whence); int __wrap_fseek(FILE *stream, long offset, int whence) { if (stream != &mocked_file_stream) { return __real_fseek(stream, offset, whence); } return 0; } int __real_feof(FILE *stream); int __wrap_feof(FILE *stream) { if (stream != &mocked_file_stream) { return __real_feof(stream); } return 0; } int __real_fclose(FILE *stream); int __wrap_fclose(FILE *stream) { if (stream != &mocked_file_stream) { return __real_fclose(stream); } return 0; } static void test_tpm2_auth_util_from_optarg_file(void **state) { UNUSED(state); tpm2_session *session; will_return(__wrap_fopen, &mocked_file_stream); will_return(__wrap_fread, (size_t) strlen(mocked_file_data)); will_return(__wrap_ftell, (long) strlen(mocked_file_data)); will_return(__wrap_ftell, (long) strlen(mocked_file_data)); tool_rc rc = tpm2_auth_util_from_optarg(NULL, "file:test_tpm2_auth_util_foobar", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, strlen(mocked_file_data)); assert_memory_equal(auth->buffer, mocked_file_data, strlen(mocked_file_data)); tpm2_session_close(&session); } #define PCR_SPECIFICATION "sha256:0,1,2,3+sha1:0,1,2,3" #define PCR_FILE "raw-pcr-file" static void test_parse_pcr_no_raw_file(void **state) { UNUSED(state); const char *policy = "pcr:" PCR_SPECIFICATION; char *pcr_str, *raw_file; bool ret = parse_pcr(policy, &pcr_str, &raw_file); assert_true(ret); assert_string_equal(pcr_str, PCR_SPECIFICATION); assert_null(raw_file); free(pcr_str); } static void test_parse_pcr_with_raw_file(void **state) { UNUSED(state); const char *policy = "pcr:" PCR_SPECIFICATION "=" PCR_FILE; char *pcr_str, *raw_file; bool ret = parse_pcr(policy, &pcr_str, &raw_file); assert_true(ret); assert_string_equal(pcr_str, PCR_SPECIFICATION); assert_string_equal(raw_file, PCR_FILE); free(pcr_str); } static void test_tpm2_auth_util_from_optarg_raw_overlength(void **state) { (void) state; tpm2_session *session = NULL; char *overlength = "this_password_is_over_64_characters_in_length_and_should_fail_XXX"; tool_rc rc = tpm2_auth_util_from_optarg(NULL, overlength, &session, true); assert_int_equal(rc, tool_rc_general_error); assert_null(session); } static void test_tpm2_auth_util_from_optarg_hex_overlength(void **state) { (void) state; tpm2_session *session = NULL; /* 65 hex chars generated via: echo \"`xxd -p -c256 -l65 /dev/urandom`\"\; */ char *overlength = "hex:ae6f6fa01589aa7b227bb6a34c7a8e0c273adbcf14195ce12391a5cc12a5c271f62088" "dbfcf1914fdf120da183ec3ad6cc78a2ffd91db40a560169961e3a6d26bf"; tool_rc rc = tpm2_auth_util_from_optarg(NULL, overlength, &session, false); assert_int_equal(rc, tool_rc_general_error); assert_null(session); } static void test_tpm2_auth_util_from_optarg_empty_str(void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 0); tpm2_session_close(&session); } static void test_tpm2_auth_util_from_optarg_empty_str_str_prefix( void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "str:", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 0); tpm2_session_close(&session); } static void test_tpm2_auth_util_from_optarg_empty_str_hex_prefix( void **state) { (void) state; tpm2_session *session; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "hex:", &session, true); assert_int_equal(rc, tool_rc_success); const TPM2B_AUTH *auth = tpm2_session_get_auth_value(session); assert_int_equal(auth->size, 0); tpm2_session_close(&session); } static void test_parse_pcr_empty(void **state) { UNUSED(state); const char *policy = "pcr:"; char *pcr_str, *raw_file; bool ret = parse_pcr(policy, &pcr_str, &raw_file); assert_false(ret); } static void test_parse_pcr_empty_pcr_specification(void **state) { UNUSED(state); const char *policy = "pcr:=" PCR_FILE; char *pcr_str, *raw_file; bool ret = parse_pcr(policy, &pcr_str, &raw_file); assert_false(ret); } static void test_parse_pcr_empty_pcr_file(void **state) { UNUSED(state); const char *policy = "pcr:" PCR_SPECIFICATION "="; char *pcr_str, *raw_file; bool ret = parse_pcr(policy, &pcr_str, &raw_file); assert_false(ret); free(pcr_str); } static int setup(void **state) { TSS2_RC rc; ESYS_CONTEXT *ectx; size_t size = sizeof(TSS2_TCTI_CONTEXT_FAKE); TSS2_TCTI_CONTEXT *tcti = malloc(size); rc = tcti_fake_initialize(tcti, &size); if (rc) { return (int)rc; } rc = Esys_Initialize(&ectx, tcti, NULL); *state = (void *)ectx; return (int)rc; } static int teardown(void **state) { TSS2_TCTI_CONTEXT *tcti; ESYS_CONTEXT *ectx = (ESYS_CONTEXT *)*state; Esys_GetTcti(ectx, &tcti); Esys_Finalize(&ectx); free(tcti); return 0; } static void test_tpm2_auth_util_get_pw_shandle(void **state) { ESYS_CONTEXT *ectx = (ESYS_CONTEXT *)*state; ESYS_TR auth_handle = ESYS_TR_NONE; ESYS_TR shandle; tpm2_session *s; tool_rc rc = tpm2_auth_util_from_optarg(NULL, "fakepass", &s, true); assert_int_equal(rc, tool_rc_success); assert_non_null(s); rc = tpm2_auth_util_get_shandle(ectx, auth_handle, s, &shandle); assert_int_equal(rc, tool_rc_success); assert_true(shandle == ESYS_TR_PASSWORD); tpm2_session_close(&s); assert_null(s); set_expected_defaults(TPM2_SE_POLICY, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); rc = tpm2_session_open(ectx, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); rc = tpm2_auth_util_get_shandle(ectx, auth_handle, s, &shandle); assert_int_equal(rc, tool_rc_success); assert_int_equal(SESSION_HANDLE, shandle); tpm2_session_close(&s); assert_null(s); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test(test_tpm2_auth_util_from_optarg_raw_noprefix), cmocka_unit_test(test_tpm2_auth_util_from_optarg_str_prefix), cmocka_unit_test(test_tpm2_auth_util_from_optarg_hex_prefix), cmocka_unit_test(test_tpm2_auth_util_from_optarg_str_escaped_hex_prefix), cmocka_unit_test_setup_teardown(test_tpm2_auth_util_get_pw_shandle, setup, teardown), cmocka_unit_test(test_tpm2_auth_util_from_optarg_file), cmocka_unit_test(test_parse_pcr_no_raw_file), cmocka_unit_test(test_parse_pcr_with_raw_file), /* negative testing */ cmocka_unit_test(test_tpm2_auth_util_from_optarg_raw_overlength), cmocka_unit_test(test_tpm2_auth_util_from_optarg_hex_overlength), cmocka_unit_test(test_tpm2_auth_util_from_optarg_empty_str), cmocka_unit_test(test_tpm2_auth_util_from_optarg_empty_str_str_prefix), cmocka_unit_test(test_tpm2_auth_util_from_optarg_empty_str_hex_prefix), cmocka_unit_test(test_parse_pcr_empty), cmocka_unit_test(test_parse_pcr_empty_pcr_specification), cmocka_unit_test(test_parse_pcr_empty_pcr_file), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_errata.c000066400000000000000000000125371412464516500210010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_errata.h" #include "tpm2_util.h" static inline void setcaps(UINT32 level, UINT32 rev, UINT32 day, UINT32 year, TSS2_RC rc) { will_return(__wrap_Esys_GetCapability, level); will_return(__wrap_Esys_GetCapability, rev); will_return(__wrap_Esys_GetCapability, day); will_return(__wrap_Esys_GetCapability, year); will_return(__wrap_Esys_GetCapability, rc); } TSS2_RC __wrap_Esys_GetCapability(ESYS_CONTEXT *context, ESYS_TR session1, ESYS_TR session2, ESYS_TR session3, TPM2_CAP capability, UINT32 property, UINT32 propertyCount, TPMI_YES_NO *moreData, TPMS_CAPABILITY_DATA **capabilityData) { UNUSED(context); UNUSED(session1); UNUSED(session2); UNUSED(session3); UNUSED(property); UNUSED(propertyCount); /* Ensure moreData is TPM2_NO, otherwise tpm2_capability_get() will make * multiple calls to Esys_CapabilityGet() */ *moreData = TPM2_NO; *capabilityData = calloc(1, sizeof(**capabilityData)); (*capabilityData)->capability = capability; TPML_TAGGED_TPM_PROPERTY *properties = &(*capabilityData)->data.tpmProperties; properties->count = 4; properties->tpmProperty[0].property = TPM2_PT_LEVEL; properties->tpmProperty[0].value = (UINT32) mock(); properties->tpmProperty[1].property = TPM2_PT_REVISION; properties->tpmProperty[1].value = (UINT32) mock(); properties->tpmProperty[2].property = TPM2_PT_DAY_OF_YEAR; properties->tpmProperty[2].value = (UINT32) mock(); properties->tpmProperty[3].property = TPM2_PT_YEAR; properties->tpmProperty[3].value = (UINT32) mock(); TSS2_RC rc = (int) mock(); /* dequeue second value */ if (rc != TSS2_RC_SUCCESS) free(*capabilityData); return rc; } #define TPM2B_PUBLIC_INIT(value) { \ .publicArea = { \ .objectAttributes = value \ } \ } static void test_tpm2_errata_no_init_and_apply(void **state) { UNUSED(state); TPM2B_PUBLIC in_public = TPM2B_PUBLIC_INIT(TPMA_OBJECT_SIGN_ENCRYPT); tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &in_public.publicArea.objectAttributes); assert_int_equal( in_public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT, TPMA_OBJECT_SIGN_ENCRYPT); } static void test_tpm2_errata_bad_init_and_apply(void **state) { UNUSED(state); setcaps(00, 116, 303, 2014, TPM2_RC_FAILURE); tpm2_errata_init((ESYS_CONTEXT *) 0xDEADBEEF); TPM2B_PUBLIC in_public = TPM2B_PUBLIC_INIT(TPMA_OBJECT_SIGN_ENCRYPT); tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &in_public.publicArea.objectAttributes); assert_int_equal( in_public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT, TPMA_OBJECT_SIGN_ENCRYPT); } static void test_tpm2_errata_init_good_and_apply(void **state) { UNUSED(state); setcaps(00, 116, 303, 2014, TPM2_RC_SUCCESS); tpm2_errata_init((ESYS_CONTEXT *) 0xDEADBEEF); TPM2B_PUBLIC in_public = TPM2B_PUBLIC_INIT(TPMA_OBJECT_SIGN_ENCRYPT); tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &in_public.publicArea.objectAttributes); assert_int_equal( in_public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT, 0); } static void test_tpm2_errata_init_good_and_no_match(void **state) { UNUSED(state); setcaps(00, 116, 4, 2015, TPM2_RC_SUCCESS); //Tss2_Sys_GetCapability tpm2_errata_init((ESYS_CONTEXT *) 0xDEADBEEF); TPM2B_PUBLIC in_public = TPM2B_PUBLIC_INIT(TPMA_OBJECT_SIGN_ENCRYPT); tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &in_public.publicArea.objectAttributes); assert_int_equal( in_public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT, TPMA_OBJECT_SIGN_ENCRYPT); } static void test_tpm2_errata_init_no_match_and_apply(void **state) { UNUSED(state); /* This will never match */ setcaps(00, 00, 00, 00, TPM2_RC_SUCCESS); //Tss2_Sys_GetCapability tpm2_errata_init((ESYS_CONTEXT *) 0xDEADBEEF); TPM2B_PUBLIC in_public = TPM2B_PUBLIC_INIT(TPMA_OBJECT_SIGN_ENCRYPT); tpm2_errata_fixup(SPEC_116_ERRATA_2_7, &in_public.publicArea.objectAttributes); assert_int_equal( in_public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT, TPMA_OBJECT_SIGN_ENCRYPT); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); const struct CMUnitTest tests[] = { /* * no_init/bad_init routines must go first as there is no way to * de-initialize. However, re-initialization will query the capabilities * and can be changed or cause a no-match situation. This is a bit of * whitebox knowledge in the ordering of these tests. */ cmocka_unit_test(test_tpm2_errata_no_init_and_apply), cmocka_unit_test(test_tpm2_errata_bad_init_and_apply), cmocka_unit_test(test_tpm2_errata_init_good_and_apply), cmocka_unit_test(test_tpm2_errata_init_good_and_no_match), cmocka_unit_test(test_tpm2_errata_init_no_match_and_apply), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_eventlog.c000066400000000000000000000473251412464516500213510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "tpm2_eventlog.h" #define TCG_DIGEST2_SHA1_SIZE (sizeof(TCG_DIGEST2) + TPM2_SHA_DIGEST_SIZE) #define TCG_DIGEST2_SHA256_SIZE (sizeof(TCG_DIGEST2) + TPM2_SHA256_DIGEST_SIZE) static bool foreach_digest2_test_callback(TCG_DIGEST2 const *digest, size_t size, void *data){ (void)digest; (void)size; (void)data; return mock_type(bool); } static void test_foreach_digest2_null(void **state){ (void)state; tpm2_eventlog_context ctx = {0}; assert_false(foreach_digest2(&ctx, 0, NULL, 0, sizeof(TCG_DIGEST2))); } static void test_foreach_digest2_size(void **state) { (void)state; uint8_t buf [sizeof(TCG_DIGEST2) - 1] = { 0, }; TCG_DIGEST2 *digest = (TCG_DIGEST2*)buf; tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; assert_false(foreach_digest2(&ctx, 0, digest, 1, sizeof(TCG_DIGEST2) - 1)); } static void test_foreach_digest2(void **state) { (void)state; uint8_t buf [TCG_DIGEST2_SHA1_SIZE] = { 0, }; TCG_DIGEST2* digest = (TCG_DIGEST2*)buf; will_return(foreach_digest2_test_callback, true); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; assert_true(foreach_digest2(&ctx, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); } static void test_foreach_digest2_cbnull(void **state){ (void)state; uint8_t buf [TCG_DIGEST2_SHA1_SIZE] = {0}; TCG_DIGEST2* digest = (TCG_DIGEST2*)buf; tpm2_eventlog_context ctx = {0}; assert_true(foreach_digest2(&ctx, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); } static void test_sha1(void **state){ (void)state; uint8_t buf [TCG_DIGEST2_SHA1_SIZE] = { 0, }; const uint8_t sha1sum[] = { 0x31,0x19,0x5d,0x69,0x35,0x16,0x3c,0x79,0xa9,0x67, 0x22,0xba,0x7d,0x4b,0x11,0x35,0x24,0x89,0xf4,0x8b, }; const int pcr_index = 3; TCG_DIGEST2 * digest = (TCG_DIGEST2*) buf; digest->AlgorithmId = TPM2_ALG_SHA1, memcpy(digest->Digest, "the magic words are:", TPM2_SHA1_DIGEST_SIZE); tpm2_eventlog_context ctx = {0}; assert_true(foreach_digest2(&ctx, pcr_index, digest, 1, TCG_DIGEST2_SHA1_SIZE)); assert_memory_equal(ctx.sha1_pcrs[pcr_index], sha1sum, sizeof(sha1sum)); } static void test_sha256(void **state){ (void)state; uint8_t buf [TCG_DIGEST2_SHA256_SIZE] = {0}; const uint8_t sha256sum[] = { 0x51,0xea,0x4e,0xa4,0x98,0xaa,0xe2,0x52, 0xf4,0xe7,0xff,0x4b,0x13,0xb6,0x3f,0xe5, 0xb5,0x7a,0xf8,0x21,0xa4,0x84,0x4e,0xe2, 0x6f,0xd8,0xdd,0x25,0xa4,0x2b,0x33,0x23, }; const int pcr_index = 3; TCG_DIGEST2 * digest = (TCG_DIGEST2*) buf; digest->AlgorithmId = TPM2_ALG_SHA256, memcpy(digest->Digest, "The Magic Words are Squeamish Ossifrage, for RSA-129 (from 1977)", TPM2_SHA256_DIGEST_SIZE); tpm2_eventlog_context ctx = {0}; assert_true(foreach_digest2(&ctx, pcr_index, digest, 1, TCG_DIGEST2_SHA256_SIZE)); assert_memory_equal(ctx.sha256_pcrs[pcr_index], sha256sum, sizeof(sha256sum)); } static void test_foreach_digest2_cbfail(void **state){ (void)state; uint8_t buf [TCG_DIGEST2_SHA1_SIZE] = { 0, }; TCG_DIGEST2* digest = (TCG_DIGEST2*)buf; will_return(foreach_digest2_test_callback, false); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback }; assert_false(foreach_digest2(&ctx, 0, digest, 1, TCG_DIGEST2_SHA1_SIZE)); } static void test_digest2_accumulator_callback(void **state) { (void)state; char buf[TCG_DIGEST2_SHA1_SIZE]; TCG_DIGEST2 *digest = (TCG_DIGEST2*)buf; size_t size = TPM2_SHA1_DIGEST_SIZE, accumulated = 0; digest->AlgorithmId = TPM2_ALG_SHA1; assert_true(digest2_accumulator_callback (digest, size, &accumulated)); assert_int_equal(accumulated, TCG_DIGEST2_SHA1_SIZE); } static void test_digest2_accumulator_callback_null(void **state) { (void)state; assert_false(digest2_accumulator_callback (NULL, 0, NULL)); } static bool test_event2hdr_callback(TCG_EVENT_HEADER2 const *eventhdr, size_t size, void *data) { (void)eventhdr; (void)size; (void)data; return mock_type(bool); } static bool test_event2_callback(TCG_EVENT2 const *event, UINT32 type, void *data, uint32_t eventlog_version) { (void)event; (void)type; (void)data; (void)eventlog_version; return mock_type(bool); } static void test_parse_event2_badhdr(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) - 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; size_t size_event = 0, size_digest = 0; assert_false(parse_event2(eventhdr, sizeof(buf), &size_event, &size_digest)); } static void test_parse_event2_baddigest(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE - 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; size_t size_event = 0, size_digest = 0; eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; assert_false(parse_event2(eventhdr, sizeof(buf), &size_event, &size_digest)); } static void test_parse_event2_badeventsize(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) - 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; size_t size_event = 0, size_digest = 0; eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; assert_false(parse_event2(eventhdr, sizeof(buf), &size_event, &size_digest)); } static void test_parse_event2_badeventbuf(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2)] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); size_t size_event = 0, size_digest = 0; eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; assert_false(parse_event2(eventhdr, sizeof(buf), &size_event, &size_digest)); } static void test_foreach_event2_version1(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 6] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)digest + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 6; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, true); will_return(test_event2_callback, true); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback, .event2_cb = test_event2_callback, .event2hdr_cb = test_event2hdr_callback, .eventlog_version = 1, }; assert_true(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_version2(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 6] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)digest + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 6; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, true); will_return(test_event2_callback, true); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback, .event2_cb = test_event2_callback, .event2hdr_cb = test_event2hdr_callback, .eventlog_version = 2, }; assert_true(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_event2hdr_fail(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; will_return(test_event2hdr_callback, false); tpm2_eventlog_context ctx = { .event2hdr_cb = test_event2hdr_callback, }; assert_false(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_digest2_fail(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, false); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback, .event2hdr_cb = test_event2hdr_callback, }; assert_false(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_parse_event2body_fail(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; eventhdr->EventType = EV_EFI_VARIABLE_BOOT; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, true); tpm2_eventlog_context ctx = { .digest2_cb = foreach_digest2_test_callback, .event2hdr_cb = test_event2hdr_callback, }; assert_false(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_event2body_version1_fail(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, true); will_return(test_event2_callback, false); tpm2_eventlog_context ctx = { .event2hdr_cb = test_event2hdr_callback, .digest2_cb = foreach_digest2_test_callback, .event2_cb = test_event2_callback, .eventlog_version = 1, }; assert_false(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_foreach_event2_event2body_version2_fail(void **state){ (void)state; char buf[sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 1] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = eventhdr->Digests; TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; event->EventSize = 1; will_return(test_event2hdr_callback, true); will_return(foreach_digest2_test_callback, true); will_return(test_event2_callback, false); tpm2_eventlog_context ctx = { .event2hdr_cb = test_event2hdr_callback, .digest2_cb = foreach_digest2_test_callback, .event2_cb = test_event2_callback, .eventlog_version = 2, }; assert_false(foreach_event2(&ctx, eventhdr, sizeof(buf))); } static void test_parse_event2body_uefivar_badsize(void **state){ (void)state; TCG_EVENT2 event = { 0, }; assert_false(parse_event2body(&event, EV_EFI_VARIABLE_DRIVER_CONFIG)); } #include static void test_parse_event2body_uefivar_badlength(void **state){ (void)state; char buf[sizeof(TCG_EVENT2) + sizeof(UEFI_VARIABLE_DATA) + sizeof(UTF16_CHAR)] = { 0, }; TCG_EVENT2 *event = (TCG_EVENT2*)buf; event->EventSize = sizeof(UEFI_VARIABLE_DATA) + sizeof(UTF16_CHAR) - 1; UEFI_VARIABLE_DATA *data = (UEFI_VARIABLE_DATA*)event->Event; data->UnicodeNameLength = 1; assert_false(parse_event2body(event, EV_EFI_VARIABLE_DRIVER_CONFIG)); } static void test_parse_event2body_firmware_blob_badlength(void **state){ (void)state; char buf[sizeof(TCG_EVENT2)] = { 0, }; TCG_EVENT2 *event = (TCG_EVENT2*)buf; event->EventSize = sizeof(UEFI_PLATFORM_FIRMWARE_BLOB) - 1; assert_false(parse_event2body(event, EV_EFI_PLATFORM_FIRMWARE_BLOB)); } static void test_specid_event_nohdr(void **state){ (void)state; TCG_EVENT event = { 0, }; TCG_EVENT_HEADER2 *next = NULL; assert_false(specid_event(&event, sizeof(event) - 1, &next)); } static void test_specid_event_badeventtype(void **state){ (void)state; TCG_EVENT event = { .eventType = EV_ACTION, }; TCG_EVENT_HEADER2 *next = NULL; assert_false(specid_event(&event, sizeof(event), &next)); } static void test_specid_event_badpcrindex(void **state){ (void)state; TCG_EVENT event = { .eventType = EV_NO_ACTION, .pcrIndex = 1, }; TCG_EVENT_HEADER2 *next = NULL; assert_false(specid_event(&event, sizeof(event), &next)); } static void test_specid_event_baddigest(void **state){ (void)state; TCG_EVENT event = { .eventType = EV_NO_ACTION, .digest = { 0x01, }, }; TCG_EVENT_HEADER2 *next = NULL; assert_false(specid_event(&event, sizeof(event), &next)); } static void test_specid_event_badeventsize(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid)] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = 1; assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event_badsize(void **state){ (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + 1] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event_noalgs(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid)] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event_nosizeforalgs(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid)] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); event_specid = (TCG_SPECID_EVENT*)event->event; event_specid->numberOfAlgorithms = 5; assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event_nosizeforvendorstruct(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_SPECID_ALG *alg; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid) + sizeof(*alg)] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); event_specid = (TCG_SPECID_EVENT*)event->event; event_specid->numberOfAlgorithms = 1; assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event_nosizeforvendordata(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_SPECID_ALG *alg; TCG_VENDOR_INFO *vendor; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid) + sizeof(*alg) + sizeof(*vendor)] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); event_specid = (TCG_SPECID_EVENT*)event->event; event_specid->numberOfAlgorithms = 1; vendor = (TCG_VENDOR_INFO*)((uintptr_t)event_specid->digestSizes + sizeof(*alg) * event_specid->numberOfAlgorithms); vendor->vendorInfoSize = 1; printf("data size: %zu\n", sizeof(buf)); assert_false(specid_event(event, sizeof(buf), &next)); } static void test_specid_event(void **state) { (void)state; TCG_EVENT *event; TCG_SPECID_EVENT *event_specid; TCG_SPECID_ALG *alg; TCG_VENDOR_INFO *vendor; TCG_EVENT_HEADER2 *next = NULL; char buf[sizeof(*event) + sizeof(*event_specid) + sizeof(*alg) + sizeof(*vendor) + 5] = { 0, }; event = (TCG_EVENT*)buf; event->eventType = EV_NO_ACTION; event->eventDataSize = sizeof(*event_specid); event_specid = (TCG_SPECID_EVENT*)event->event; event_specid->numberOfAlgorithms = 1; vendor = (TCG_VENDOR_INFO*)((uintptr_t)event_specid->digestSizes + sizeof(*alg) * event_specid->numberOfAlgorithms); vendor->vendorInfoSize = 5; printf("sizeof(buf): %zu\n", sizeof(buf)); assert_true(specid_event(event, sizeof(buf), &next)); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(test_foreach_digest2_null), cmocka_unit_test(test_foreach_digest2_size), cmocka_unit_test(test_foreach_digest2), cmocka_unit_test(test_foreach_digest2_cbfail), cmocka_unit_test(test_foreach_digest2_cbnull), cmocka_unit_test(test_sha1), cmocka_unit_test(test_sha256), cmocka_unit_test(test_digest2_accumulator_callback), cmocka_unit_test(test_digest2_accumulator_callback_null), cmocka_unit_test(test_parse_event2_badhdr), cmocka_unit_test(test_parse_event2_baddigest), cmocka_unit_test(test_parse_event2_badeventsize), cmocka_unit_test(test_parse_event2_badeventbuf), cmocka_unit_test(test_foreach_event2_version1), cmocka_unit_test(test_foreach_event2_version2), cmocka_unit_test(test_foreach_event2_event2hdr_fail), cmocka_unit_test(test_foreach_event2_event2body_version1_fail), cmocka_unit_test(test_foreach_event2_event2body_version2_fail), cmocka_unit_test(test_foreach_event2_digest2_fail), cmocka_unit_test(test_foreach_event2_parse_event2body_fail), cmocka_unit_test(test_parse_event2body_uefivar_badsize), cmocka_unit_test(test_parse_event2body_uefivar_badlength), cmocka_unit_test(test_parse_event2body_firmware_blob_badlength), cmocka_unit_test(test_specid_event_nohdr), cmocka_unit_test(test_specid_event_badeventtype), cmocka_unit_test(test_specid_event_badpcrindex), cmocka_unit_test(test_specid_event_baddigest), cmocka_unit_test(test_specid_event_badeventsize), cmocka_unit_test(test_specid_event_badsize), cmocka_unit_test(test_specid_event_noalgs), cmocka_unit_test(test_specid_event_nosizeforalgs), cmocka_unit_test(test_specid_event_nosizeforvendorstruct), cmocka_unit_test(test_specid_event_nosizeforvendordata), cmocka_unit_test(test_specid_event), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_eventlog_yaml.c000066400000000000000000000135661412464516500223730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "tpm2_eventlog_yaml.h" #define TCG_DIGEST2_SHA1_SIZE (sizeof(TCG_DIGEST2) + TPM2_SHA_DIGEST_SIZE) #define def_eventtype_to_string(ev) \ static void eventtype_to_string_##ev(void **state){ \ (void)state; \ assert_string_equal(eventtype_to_string(ev), #ev); \ } def_eventtype_to_string(EV_PREBOOT_CERT) def_eventtype_to_string(EV_POST_CODE) def_eventtype_to_string(EV_UNUSED) def_eventtype_to_string(EV_NO_ACTION) def_eventtype_to_string(EV_SEPARATOR) def_eventtype_to_string(EV_ACTION) def_eventtype_to_string(EV_EVENT_TAG) def_eventtype_to_string(EV_S_CRTM_CONTENTS) def_eventtype_to_string(EV_S_CRTM_VERSION) def_eventtype_to_string(EV_CPU_MICROCODE) def_eventtype_to_string(EV_PLATFORM_CONFIG_FLAGS) def_eventtype_to_string(EV_TABLE_OF_DEVICES) def_eventtype_to_string(EV_COMPACT_HASH) def_eventtype_to_string(EV_IPL) def_eventtype_to_string(EV_IPL_PARTITION_DATA) def_eventtype_to_string(EV_NONHOST_CODE) def_eventtype_to_string(EV_NONHOST_CONFIG) def_eventtype_to_string(EV_NONHOST_INFO) def_eventtype_to_string(EV_OMIT_BOOT_DEVICE_EVENTS) def_eventtype_to_string(EV_EFI_VARIABLE_DRIVER_CONFIG) def_eventtype_to_string(EV_EFI_VARIABLE_BOOT) def_eventtype_to_string(EV_EFI_BOOT_SERVICES_APPLICATION) def_eventtype_to_string(EV_EFI_BOOT_SERVICES_DRIVER) def_eventtype_to_string(EV_EFI_RUNTIME_SERVICES_DRIVER) def_eventtype_to_string(EV_EFI_GPT_EVENT) def_eventtype_to_string(EV_EFI_ACTION) def_eventtype_to_string(EV_EFI_PLATFORM_FIRMWARE_BLOB) def_eventtype_to_string(EV_EFI_HANDOFF_TABLES) def_eventtype_to_string(EV_EFI_VARIABLE_AUTHORITY) static void eventtype_to_string_default(void **state) { (void)state; assert_string_equal(eventtype_to_string(666), "Unknown event type"); } static void test_yaml_digest2_callback(void **state) { (void)state; uint8_t buf [TCG_DIGEST2_SHA1_SIZE]; TCG_DIGEST2 *digest = (TCG_DIGEST2*)buf; size_t count = 0; digest->AlgorithmId = TPM2_ALG_SHA1; assert_true(yaml_digest2_callback(digest, TPM2_SHA1_DIGEST_SIZE, &count)); } static void test_yaml_event2data_version1(void **state) { (void)state; uint8_t buf [sizeof(TCG_EVENT2) + 6]; TCG_EVENT2 *event = (TCG_EVENT2*)buf; event->EventSize = 6; assert_true(yaml_event2data(event, EV_PREBOOT_CERT, 1)); } static void test_yaml_event2data_version2(void **state) { (void)state; uint8_t buf [sizeof(TCG_EVENT2) + 6]; TCG_EVENT2 *event = (TCG_EVENT2*)buf; event->EventSize = 6; assert_true(yaml_event2data(event, EV_PREBOOT_CERT, 2)); } static void test_yaml_event2hdr_callback(void **state){ (void)state; uint8_t buf [sizeof(TCG_EVENT_HEADER2) + TCG_DIGEST2_SHA1_SIZE + sizeof(TCG_EVENT2) + 2] = { 0, }; TCG_EVENT_HEADER2 *eventhdr = (TCG_EVENT_HEADER2*)buf; TCG_DIGEST2 *digest = (TCG_DIGEST2*)(eventhdr->Digests); TCG_EVENT2 *event = (TCG_EVENT2*)(buf + sizeof(*eventhdr) + TCG_DIGEST2_SHA1_SIZE); size_t count = 0; eventhdr->DigestCount = 1; digest->AlgorithmId = TPM2_ALG_SHA1; digest->Digest[0] = 0xef; event->EventSize = 2; assert_true(yaml_event2hdr_callback(eventhdr, sizeof(buf), &count)); } static void test_yaml_event2hdr_callback_nulldata(void **state){ (void)state; assert_false(yaml_event2hdr_callback(NULL, 0, NULL)); } static void test_yaml_eventlog(void **state){ (void)state; assert_false(yaml_eventlog(NULL, 0, 1)); } int main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test(eventtype_to_string_EV_PREBOOT_CERT), cmocka_unit_test(eventtype_to_string_EV_POST_CODE), cmocka_unit_test(eventtype_to_string_EV_UNUSED), cmocka_unit_test(eventtype_to_string_EV_NO_ACTION), cmocka_unit_test(eventtype_to_string_EV_SEPARATOR), cmocka_unit_test(eventtype_to_string_EV_ACTION), cmocka_unit_test(eventtype_to_string_EV_EVENT_TAG), cmocka_unit_test(eventtype_to_string_EV_S_CRTM_CONTENTS), cmocka_unit_test(eventtype_to_string_EV_S_CRTM_VERSION), cmocka_unit_test(eventtype_to_string_EV_CPU_MICROCODE), cmocka_unit_test(eventtype_to_string_EV_PLATFORM_CONFIG_FLAGS), cmocka_unit_test(eventtype_to_string_EV_TABLE_OF_DEVICES), cmocka_unit_test(eventtype_to_string_EV_COMPACT_HASH), cmocka_unit_test(eventtype_to_string_EV_IPL), cmocka_unit_test(eventtype_to_string_EV_IPL_PARTITION_DATA), cmocka_unit_test(eventtype_to_string_EV_NONHOST_CODE), cmocka_unit_test(eventtype_to_string_EV_NONHOST_CONFIG), cmocka_unit_test(eventtype_to_string_EV_NONHOST_INFO), cmocka_unit_test(eventtype_to_string_EV_OMIT_BOOT_DEVICE_EVENTS), cmocka_unit_test(eventtype_to_string_EV_EFI_VARIABLE_DRIVER_CONFIG), cmocka_unit_test(eventtype_to_string_EV_EFI_VARIABLE_BOOT), cmocka_unit_test(eventtype_to_string_EV_EFI_BOOT_SERVICES_APPLICATION), cmocka_unit_test(eventtype_to_string_EV_EFI_BOOT_SERVICES_DRIVER), cmocka_unit_test(eventtype_to_string_EV_EFI_RUNTIME_SERVICES_DRIVER), cmocka_unit_test(eventtype_to_string_EV_EFI_GPT_EVENT), cmocka_unit_test(eventtype_to_string_EV_EFI_ACTION), cmocka_unit_test(eventtype_to_string_EV_EFI_PLATFORM_FIRMWARE_BLOB), cmocka_unit_test(eventtype_to_string_EV_EFI_HANDOFF_TABLES), cmocka_unit_test(eventtype_to_string_EV_EFI_VARIABLE_AUTHORITY), cmocka_unit_test(eventtype_to_string_default), cmocka_unit_test(test_yaml_event2hdr_callback), cmocka_unit_test(test_yaml_event2hdr_callback_nulldata), cmocka_unit_test(test_yaml_digest2_callback), cmocka_unit_test(test_yaml_event2data_version1), cmocka_unit_test(test_yaml_event2data_version2), cmocka_unit_test(test_yaml_eventlog), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_header.c000066400000000000000000000142011412464516500207410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "tpm2_header.h" static void test_tpm_command_header(void **state) { (void) state; UINT8 command_bytes[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7f }; tpm2_command_header *c = tpm2_command_header_from_bytes(command_bytes); assert_true(c->tag == 0x0180); assert_true(c->size == 0x16000000); assert_true(c->command_code == 0x7a010000); /* everything from bytes should be the same as the byte array */ assert_memory_equal(c->bytes, command_bytes, sizeof(command_bytes)); /* everything from data should be the same */ assert_memory_equal(c->data, command_bytes + 10, sizeof(command_bytes) - 10); TPMI_ST_COMMAND_TAG tag = tpm2_command_header_get_tag(c); UINT32 size_with_header = tpm2_command_header_get_size(c, true); UINT32 size_with_out_header = tpm2_command_header_get_size(c, false); TPM2_CC cc = tpm2_command_header_get_code(c); assert_true(tag == 0x8001); assert_true(size_with_header == 0x16); assert_true(size_with_out_header == 0x16 - TPM2_COMMAND_HEADER_SIZE); assert_true(cc == 0x17a); } static void test_tpm_response_header(void **state) { (void) state; unsigned char response_bytes[] = { 0x80, 0x01, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x01, 0x00, 0x32, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x07, 0xdf, 0x00, 0x00, 0x01, 0x05, 0x49, 0x42, 0x4d, 0x20, 0x00, 0x00, 0x01, 0x06, 0x53, 0x57, 0x20, 0x20, 0x00, 0x00, 0x01, 0x07, 0x20, 0x54, 0x50, 0x4d, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x0b, 0x20, 0x14, 0x07, 0x11, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x11, 0x06, 0x28, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x05, 0xf0, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00 }; tpm2_response_header *r = tpm2_response_header_from_bytes(response_bytes); assert_true(r->tag == 0x0180); assert_true(r->size == 0x1b020000); assert_true(r->response_code == 0x00); /* everything from bytes should be the same as the byte array */ assert_memory_equal(r->bytes, response_bytes, sizeof(response_bytes)); /* everything from data should be the same */ assert_memory_equal(r->data, response_bytes + 10, sizeof(response_bytes) - 10); TPMI_ST_COMMAND_TAG tag = tpm2_response_header_get_tag(r); UINT32 size_with_header = tpm2_response_header_get_size(r, true); UINT32 size_with_out_header = tpm2_response_header_get_size(r, false); TSS2_RC rc = tpm2_response_header_get_code(r); assert_true(tag == 0x8001); assert_true(size_with_header == 0x21b); assert_true(size_with_out_header == 0x21b - TPM2_RESPONSE_HEADER_SIZE); assert_true(rc == 0x00); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test(test_tpm_command_header), cmocka_unit_test(test_tpm_response_header), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_policy.c000066400000000000000000000241231412464516500210140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include "pcr.h" #include "tpm2_policy.h" #include "tpm2_util.h" typedef struct pcr_data pcr_data; struct pcr_data { TPML_DIGEST values; }; typedef struct test_file test_file; struct test_file { char *path; FILE *file; }; /* Passing tests and static data are hardcoded around this sel spec */ #define PCR_SEL_SPEC "sha256:0,1,2,3" /* * Dummy value for the session handle read by the wrapped version of: * Esys_StartAuthSession */ #define SESSION_HANDLE 0xDEADBEEF /* dummy handle for esys context */ #define ESAPI_CONTEXT ((ESYS_CONTEXT *)0xDEADBEEF) /* Any PCR read returns this value */ static TPM2B_DIGEST pcr_value = { .size = 32, .buffer = { 0x96, 0xa7, 0xfa, 0xaf, 0x16, 0x09, 0xb6, 0x50, 0xa4, 0xf2, 0x88, 0xc0, 0x90, 0x4f, 0x04, 0x83, 0x6e, 0xca, 0xda, 0x2f, 0x49, 0x78, 0x06, 0x94, 0x86, 0xa2, 0xbb, 0x02, 0xf2, 0xf0, 0x43, 0xea } }; /* The expected hash for the pcr selection of sha256:0,1,2,3 */ static TPM2B_DIGEST expected_policy_digest = { .size = 32, .buffer = { 0x62, 0x69, 0x69, 0xce, 0xa7, 0xc2, 0xea, 0x7a, 0xf8, 0x86, 0xf4, 0xb5, 0x09, 0xa5, 0xb8, 0x3a, 0xb3, 0x3b, 0x3a, 0x75, 0x75, 0x5d, 0x17, 0x40, 0x38, 0xa8, 0xd3, 0x33, 0x0f, 0xa7, 0x2a, 0xd4 } }; TSS2_RC __wrap_Esys_StartAuthSession(ESYS_CONTEXT *esysContext, ESYS_TR tpmKey, ESYS_TR bind, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_NONCE *nonceCaller, TPM2_SE sessionType, const TPMT_SYM_DEF *symmetric, TPMI_ALG_HASH authHash, ESYS_TR *sessionHandle) { UNUSED(esysContext); UNUSED(tpmKey); UNUSED(bind); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); UNUSED(nonceCaller); UNUSED(sessionType); UNUSED(symmetric); UNUSED(authHash); *sessionHandle = SESSION_HANDLE; return TPM2_RC_SUCCESS; } /* * The current digest passed via PolicyPCR and * PolicyGetDigest. */ static TPM2B_DIGEST current_digest; TSS2_RC __wrap_Esys_PolicyPCR(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPM2B_DIGEST *pcrDigest, const TPML_PCR_SELECTION *pcrs) { UNUSED(esysContext); UNUSED(policySession); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); UNUSED(pcrs); /* * Set the computed digest, which will be retrieved via * a call to Esys_PolicyGetDigest */ current_digest = *pcrDigest; return TPM2_RC_SUCCESS; } TSS2_RC __wrap_Esys_PolicyGetDigest(ESYS_CONTEXT *esysContext, ESYS_TR policySession, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, TPM2B_DIGEST **policyDigest) { UNUSED(esysContext); UNUSED(policySession); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); *policyDigest = ¤t_digest; return TPM2_RC_SUCCESS; } TSS2_RC __wrap_Esys_PCR_Read(ESYS_CONTEXT *esysContext, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3, const TPML_PCR_SELECTION *pcrSelectionIn, UINT32 *pcrUpdateCounter, TPML_PCR_SELECTION **pcrSelectionOut, TPML_DIGEST **pcrValues) { UNUSED(esysContext); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); UNUSED(pcrSelectionIn); UNUSED(pcrUpdateCounter); UNUSED(pcrSelectionOut); *pcrValues = calloc(1, sizeof(TPML_DIGEST)); if (*pcrValues == NULL) { return TPM2_RC_FAILURE; } UINT32 i; /* NOTE: magic number of 4... The prior (SAPI) implementation had a * semi-populated pcrValues with an appropriate count value set. * This ESAPI call allocates the pcrValues out-value and thus we don't have * an appropriate count number at call time, therefore we hard-code the * expected value for the *one* call we're currently making in this unit * test. */ for (i = 0; i < 4; i++) { (*pcrValues)->digests[i] = pcr_value; } return TPM2_RC_SUCCESS; } TSS2_RC __wrap_Esys_FlushContext(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) { UNUSED(esysContext); UNUSED(flushHandle); return TSS2_RC_SUCCESS; } static void test_tpm2_policy_build_pcr_good(void **state) { UNUSED(state); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(ESAPI_CONTEXT, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); TPML_PCR_SELECTION pcr_selections; bool res = pcr_parse_selections(PCR_SEL_SPEC, &pcr_selections); assert_true(res); rc = tpm2_policy_build_pcr(ESAPI_CONTEXT, s, NULL, &pcr_selections, NULL); assert_int_equal(rc, tool_rc_success); TPM2B_DIGEST *policy_digest; rc = tpm2_policy_get_digest(ESAPI_CONTEXT, s, &policy_digest); assert_int_equal(rc, tool_rc_success); assert_int_equal(policy_digest->size, expected_policy_digest.size); assert_memory_equal(policy_digest->buffer, expected_policy_digest.buffer, expected_policy_digest.size); tpm2_session_close(&s); assert_null(s); } static test_file *test_file_new(void) { test_file *tf = malloc(sizeof(test_file)); if (!tf) { return NULL; } tf->path = strdup("xxx_test_tpm2_policy_xxx.test"); if (!tf->path) { free(tf); return NULL; } tf->file = fopen(tf->path, "w+b"); if (!tf->file) { free(tf->path); free(tf); return NULL; } return tf; } static void test_file_free(test_file *tf) { assert_non_null(tf); int rc = remove(tf->path); assert_return_code(rc, errno); free(tf->path); fclose(tf->file); free(tf); } static int test_setup(void **state) { test_file *tf = test_file_new(); assert_non_null(tf); *state = tf; return 0; } static int test_teardown(void **state) { test_file *tf = (test_file *) *state; test_file_free(tf); return 0; } static test_file *test_file_from_state(void **state) { test_file *f = (test_file *) *state; assert_non_null(f); return f; } static void test_tpm2_policy_build_pcr_file_good(void **state) { test_file *tf = test_file_from_state(state); assert_non_null(tf); /* * This PCR selection must not be to big to fit in the selection * array at index 0 byte index 0. * * If it is, the file generation below needs to change. */ TPML_PCR_SELECTION pcr_selections; bool res = pcr_parse_selections(PCR_SEL_SPEC, &pcr_selections); assert_true(res); /* * create a file with the expected PCR hashes based on the number of pcr * selections. We know that the PCR selection above will always be in the * first selection array in the first byte. */ UINT32 i; UINT32 cnt = tpm2_util_pop_count( pcr_selections.pcrSelections[0].pcrSelect[0]); for (i = 0; i < cnt; i++) { TPM2B_DIGEST *d = &pcr_value; size_t num = fwrite(d->buffer, d->size, 1, tf->file); assert_int_equal(num, 1); } int rc = fflush(tf->file); assert_int_equal(rc, 0); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc trc = tpm2_session_open(ESAPI_CONTEXT, d, &s); assert_int_equal(trc, tool_rc_success); assert_non_null(s); trc = tpm2_policy_build_pcr(ESAPI_CONTEXT, s, tf->path, &pcr_selections, NULL); assert_int_equal(trc, tool_rc_success); TPM2B_DIGEST *policy_digest; trc = tpm2_policy_get_digest(ESAPI_CONTEXT, s, &policy_digest); assert_int_equal(rc, tool_rc_success); assert_int_equal(policy_digest->size, expected_policy_digest.size); assert_memory_equal(policy_digest->buffer, expected_policy_digest.buffer, expected_policy_digest.size); tpm2_session_close(&s); assert_null(s); } static void test_tpm2_policy_build_pcr_file_bad_size(void **state) { test_file *tf = test_file_from_state(state); assert_non_null(tf); /* * This PCR selection must not be to big to fit in the selection * array at index 0 byte index 0. * * If it is, the file generation below needs to change. */ TPML_PCR_SELECTION pcr_selections; bool res = pcr_parse_selections(PCR_SEL_SPEC, &pcr_selections); assert_true(res); /* * create a file with the expected PCR hashes based on the number of pcr * selections. We know that the PCR selection above will always be in the * first selection array in the first byte. */ UINT32 i; /* force the size to be bad here by subtracting 1 */ UINT32 cnt = tpm2_util_pop_count( pcr_selections.pcrSelections[0].pcrSelect[0]) - 1; for (i = 0; i < cnt; i++) { TPM2B_DIGEST *d = &pcr_value; size_t num = fwrite(d->buffer, d->size, 1, tf->file); assert_int_equal(num, 1); } int rc = fflush(tf->file); assert_int_equal(rc, 0); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc trc = tpm2_session_open(ESAPI_CONTEXT, d, &s); assert_int_equal(trc, tool_rc_success); assert_non_null(s); trc = tpm2_policy_build_pcr(ESAPI_CONTEXT, s, tf->path, &pcr_selections, NULL); tpm2_session_close(&s); assert_null(s); assert_int_equal(trc, tool_rc_general_error); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); const struct CMUnitTest tests[] = { cmocka_unit_test(test_tpm2_policy_build_pcr_good), cmocka_unit_test_setup_teardown(test_tpm2_policy_build_pcr_file_good, test_setup, test_teardown), cmocka_unit_test_setup_teardown(test_tpm2_policy_build_pcr_file_bad_size, test_setup, test_teardown) }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_session.c000066400000000000000000000173711412464516500212070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include "test_session_common.h" #include "tpm2_session.h" ESYS_TR _save_handle; static void test_tpm2_create_dummy_context(TPMS_CONTEXT *context) { context->hierarchy = TPM2_RH_ENDORSEMENT; context->savedHandle = 2147483648; context->sequence = 10; context->contextBlob.size = 200; memset(context->contextBlob.buffer, '\0', context->contextBlob.size); } tool_rc __wrap_tpm2_context_save(ESYS_CONTEXT *esysContext, ESYS_TR saveHandle, TPMS_CONTEXT **context) { UNUSED(esysContext); // context should be non-null or bool files_save_tpm_context_to_file() // segfaults TPMS_CONTEXT *dummy_context = calloc(1, sizeof(TPMS_CONTEXT)); test_tpm2_create_dummy_context(dummy_context); *context = dummy_context; _save_handle = saveHandle; return tool_rc_success; } TSS2_RC __wrap_Esys_ContextLoad(ESYS_CONTEXT *esysContext, const TPMS_CONTEXT *context, ESYS_TR *loadedHandle) { UNUSED(esysContext); UNUSED(context); *loadedHandle = _save_handle; return TPM2_RC_SUCCESS; } static TSS2_RC policy_restart_return() { return (TSS2_RC) mock(); } TSS2_RC __wrap_Esys_PolicyRestart(ESYS_CONTEXT *esysContext, ESYS_TR sessionHandle, ESYS_TR shandle1, ESYS_TR shandle2, ESYS_TR shandle3) { UNUSED(esysContext); UNUSED(sessionHandle); UNUSED(shandle1); UNUSED(shandle2); UNUSED(shandle3); return policy_restart_return(); } static ESYS_CONTEXT *CONTEXT = ((ESYS_CONTEXT *) 0xDEADBEEF); TSS2_RC __wrap_Esys_TR_GetName(ESYS_CONTEXT *esysContext, ESYS_TR handle, TPM2B_NAME **name) { UNUSED(esysContext); UNUSED(handle); *name = malloc(sizeof(TPM2B_NAME)); size_t offset = 0; TSS2_RC rc = Tss2_MU_TPM2_HANDLE_Marshal(SESSION_HANDLE, &(*name)->name[0], sizeof(TPM2_HANDLE), &offset); (*name)->size = offset; return rc; } TSS2_RC __wrap_tpm2_flush_context(ESYS_CONTEXT *esysContext, ESYS_TR flushHandle) { UNUSED(esysContext); UNUSED(flushHandle); return TSS2_RC_SUCCESS; } static void test_tpm2_session_defaults_good(void **state) { UNUSED(state); set_expected_defaults(TPM2_SE_POLICY, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); ESYS_TR handle = tpm2_session_get_handle(s); assert_int_equal(handle, SESSION_HANDLE); TPMI_ALG_HASH auth_hash = tpm2_session_get_authhash(s); assert_int_equal(auth_hash, TPM2_ALG_SHA256); tpm2_session_close(&s); assert_null(s); } static void test_tpm2_session_setters_good(void **state) { UNUSED(state); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_TRIAL); assert_non_null(d); tpm2_session_set_authhash(d, TPM2_ALG_SHA512); TPMT_SYM_DEF symmetric = { .algorithm = TPM2_ALG_AES, .keyBits = { .aes = 256 }, .mode = { .aes = 42 }, }; tpm2_session_set_symmetric(d, &symmetric); tpm2_session_set_bind(d, 42); TPM2B_NONCE nonce = { .size = 5, .buffer = { 'n', 'o', 'n', 'c', 'e' } }; tpm2_session_set_nonce_caller(d, &nonce); tpm2_session_set_key(d, 0x1234); set_expected(0x1234, 42, TPM2_SE_TRIAL, &symmetric, TPM2_ALG_SHA512, &nonce, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); TPMI_SH_AUTH_SESSION handle = tpm2_session_get_handle(s); assert_int_equal(handle, SESSION_HANDLE); TPMI_ALG_HASH auth_hash = tpm2_session_get_authhash(s); assert_int_equal(auth_hash, TPM2_ALG_SHA512); tpm2_session_close(&s); assert_null(s); } static void test_tpm2_session_defaults_bad(void **state) { UNUSED(state); set_expected_defaults(TPM2_SE_POLICY, SESSION_HANDLE, TPM2_RC_FAILURE); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); assert_int_equal(rc, tool_rc_general_error); assert_null(s); } static int test_session_setup(void **state) { int rc = (*state = tmpnam(NULL)) == NULL; return rc; } static int test_session_teardown(void **state) { int rc = unlink((char *) *state); return rc; } static void test_tpm2_session_save(void **state) { set_expected_defaults(TPM2_SE_POLICY, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session_set_path(d, (char *) *state); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); //OPEN assert_int_equal(rc, tool_rc_success); assert_non_null(s); rc = tpm2_session_close(&s); //CLOSE assert_int_equal(rc, tool_rc_success); assert_null(s); rc = tpm2_session_restore(NULL, (char *) *state, false, &s); //RESTORE assert_int_equal(rc, tool_rc_success); assert_non_null(s); tpm2_session_close(&s); //CLOSE assert_null(s); } static void test_tpm2_session_restart(void **state) { UNUSED(state); set_expected_defaults(TPM2_SE_POLICY, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY); assert_non_null(d); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); will_return(policy_restart_return, TPM2_RC_SUCCESS); rc = tpm2_session_restart(CONTEXT, s); assert_int_equal(rc, tool_rc_success); will_return(policy_restart_return, TPM2_RC_HANDLE); rc = tpm2_session_restart(CONTEXT, s); assert_int_equal(rc, tool_rc_general_error); tpm2_session_close(&s); assert_null(s); } static void test_tpm2_session_is_trial_test(void **state) { UNUSED(state); set_expected_defaults(TPM2_SE_TRIAL, SESSION_HANDLE, TPM2_RC_SUCCESS); tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_TRIAL); assert_non_null(d); tpm2_session *s = NULL; tool_rc rc = tpm2_session_open(CONTEXT, d, &s); assert_int_equal(rc, tool_rc_success); assert_non_null(s); TPM2_SE type = tpm2_session_get_type(s); assert_int_equal(type, TPM2_SE_TRIAL); bool is_trial = tpm2_session_is_trial(s); assert_true(is_trial); tpm2_session_close(&s); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char *argv[]) { UNUSED(argc); UNUSED(argv); const struct CMUnitTest tests[] = { /* * no_init/bad_init routines must go first as there is no way to * de-initialize. However, re-initialization will query the capabilities * and can be changed or cause a no-match situation. This is a bit of * whitebox knowledge in the ordering of these tests. */ cmocka_unit_test(test_tpm2_session_defaults_good), cmocka_unit_test(test_tpm2_session_setters_good), cmocka_unit_test(test_tpm2_session_defaults_bad), cmocka_unit_test_setup_teardown(test_tpm2_session_save, test_session_setup, test_session_teardown), cmocka_unit_test(test_tpm2_session_restart), cmocka_unit_test(test_tpm2_session_is_trial_test) }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/test/unit/test_tpm2_util.c000066400000000000000000000132731412464516500204760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tpm2_hierarchy.h" #include "tpm2_util.h" static void test_tpm2_util_handle_from_optarg_NULL(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg(NULL, &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_false(result); } static void test_tpm2_util_handle_from_optarg_empty(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_false(result); } static void test_tpm2_util_handle_from_optarg_invalid_id(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("q", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_false(result); } static void test_tpm2_util_handle_from_optarg_invalid_str(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("nope", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_false(result); } static void test_tpm2_util_handle_from_optarg_valid_ids(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("o", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_true(result); assert_int_equal(h, TPM2_RH_OWNER); result = tpm2_util_handle_from_optarg("p", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_true(result); assert_int_equal(h, TPM2_RH_PLATFORM); result = tpm2_util_handle_from_optarg("e", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_true(result); assert_int_equal(h, TPM2_RH_ENDORSEMENT); result = tpm2_util_handle_from_optarg("n", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_true(result); assert_int_equal(h, TPM2_RH_NULL); result = tpm2_util_handle_from_optarg("0x81010009", &h, TPM2_HANDLE_ALL_W_NV); assert_true(result); assert_int_equal(h, 0x81010009); } static void test_tpm2_util_handle_from_optarg_valid_ids_disabled(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("o", &h, TPM2_HANDLE_FLAGS_N); assert_false(result); result = tpm2_util_handle_from_optarg("p", &h, TPM2_HANDLE_FLAGS_O); assert_false(result); result = tpm2_util_handle_from_optarg("e", &h, TPM2_HANDLE_FLAGS_P); assert_false(result); result = tpm2_util_handle_from_optarg("n", &h, TPM2_HANDLE_FLAGS_E); assert_false(result); result = tpm2_util_handle_from_optarg("0x81010009", &h, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); assert_false(result); } static void test_tpm2_util_handle_from_optarg_valid_ids_enabled(void **state) { UNUSED(state); TPMI_RH_PROVISION h; bool result = tpm2_util_handle_from_optarg("o", &h, TPM2_HANDLE_FLAGS_O); assert_true(result); assert_int_equal(h, TPM2_RH_OWNER); result = tpm2_util_handle_from_optarg("p", &h, TPM2_HANDLE_FLAGS_P); assert_true(result); assert_int_equal(h, TPM2_RH_PLATFORM); result = tpm2_util_handle_from_optarg("e", &h, TPM2_HANDLE_FLAGS_E); assert_true(result); assert_int_equal(h, TPM2_RH_ENDORSEMENT); result = tpm2_util_handle_from_optarg("n", &h, TPM2_HANDLE_FLAGS_N); assert_true(result); assert_int_equal(h, TPM2_RH_NULL); } static void test_tpm2_util_handle_from_optarg_nv_valid_range(void **state) { UNUSED(state); TPMI_RH_PROVISION h; /* * NV index specified as NV:offset */ bool result = tpm2_util_handle_from_optarg("1", &h, TPM2_HANDLE_FLAGS_NV); assert_true(result); assert_int_equal(h, 0x01000001); /* * NV index specified as full raw handle */ result = tpm2_util_handle_from_optarg("0x01000002", &h, TPM2_HANDLE_FLAGS_NV); assert_true(result); assert_int_equal(h, 0x01000002); } static void test_tpm2_util_handle_from_optarg_nv_invalid_offset(void **state) { UNUSED(state); TPMI_RH_PROVISION h; /* * No offset specified */ bool result = tpm2_util_handle_from_optarg("", &h, TPM2_HANDLE_FLAGS_NV); assert_false(result); /* * Offset is non hex string */ result = tpm2_util_handle_from_optarg("random", &h, TPM2_HANDLE_FLAGS_NV); assert_false(result); /* * Offset is larger than TPM2_HR_HANDLE_MASK */ result = tpm2_util_handle_from_optarg("0x12345678", &h, TPM2_HANDLE_FLAGS_NV); assert_false(result); /* * Wrongly specify NV index as raw handle and disable NV in flags */ result = tpm2_util_handle_from_optarg("0x01000001", &h, TPM2_HANDLE_FLAGS_O); assert_false(result); } /* link required symbol, but tpm2_tool.c declares it AND main, which * we have a main below for cmocka tests. */ bool output_enabled = true; int main(int argc, char* argv[]) { (void) argc; (void) argv; const struct CMUnitTest tests[] = { cmocka_unit_test(test_tpm2_util_handle_from_optarg_NULL), cmocka_unit_test(test_tpm2_util_handle_from_optarg_empty), cmocka_unit_test(test_tpm2_util_handle_from_optarg_invalid_id), cmocka_unit_test(test_tpm2_util_handle_from_optarg_invalid_str), cmocka_unit_test(test_tpm2_util_handle_from_optarg_valid_ids), cmocka_unit_test(test_tpm2_util_handle_from_optarg_valid_ids_disabled), cmocka_unit_test(test_tpm2_util_handle_from_optarg_valid_ids_enabled), cmocka_unit_test(test_tpm2_util_handle_from_optarg_nv_valid_range), cmocka_unit_test(test_tpm2_util_handle_from_optarg_nv_invalid_offset), }; return cmocka_run_group_tests(tests, NULL, NULL); } tpm2-tools-5.2/tools/000077500000000000000000000000001412464516500145505ustar00rootroot00000000000000tpm2-tools-5.2/tools/.gitignore000066400000000000000000000000341412464516500165350ustar00rootroot00000000000000* !*/ !.gitignore !*.c !*.h tpm2-tools-5.2/tools/fapi/000077500000000000000000000000001412464516500154675ustar00rootroot00000000000000tpm2-tools-5.2/tools/fapi/tss2_authorizepolicy.c000066400000000000000000000042461412464516500220460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *policyPath; char const *keyPath; /* the path to the signing key */ char const *policyRef; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.policyPath = value; break; case 'p': ctx.keyPath = value; break; case 'r': ctx.policyRef = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"policyPath", required_argument, NULL, 'P'}, {"keyPath", required_argument, NULL, 'p'}, {"policyRef", required_argument, NULL, 'r'}, }; return (*opts = tpm2_options_new ("P:p:r.", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.policyPath) { fprintf (stderr, "policy path to sign is missing, pass" \ "--policyPath\n"); return -1; } if (!ctx.keyPath) { fprintf (stderr, "key path for signing key is missing, pass" \ "--keyPath\n"); return -1; } /* Read ciphertext file */ TSS2_RC r; uint8_t *policyRef = NULL; size_t policyRefSize = 0; if (ctx.policyRef){ r = open_read_and_close (ctx.policyRef, (void**)&policyRef, &policyRefSize); if (r){ return 1; } } /* Execute FAPI command with passed arguments */ r = Fapi_AuthorizePolicy (fctx, ctx.policyPath, ctx.keyPath, policyRef, policyRefSize); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_AuthorizePolicy", r); free (policyRef); return 1; } free (policyRef); return 0; } TSS2_TOOL_REGISTER("authorizepolicy", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_changeauth.c000066400000000000000000000037411412464516500207220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* needed to conditionally free variable authValue */ static bool has_asked_for_password = false; /* Context struct used to store passed commandline parameters */ static struct cxt { char *entityPath; char *authValue; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'a': ctx.authValue = value; break; case 'p': ctx.entityPath = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"authValue", required_argument, NULL, 'a'}, {"entityPath", required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("a:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.entityPath) { fprintf (stderr, "No entity path provided, use --entityPath\n"); return -1; } /* If no authValue was given, prompt the user interactively */ if (!ctx.authValue) { ctx.authValue = ask_for_password (); has_asked_for_password = true; if (!ctx.authValue){ return 1; /* User entered two different passwords */ } } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_ChangeAuth(fctx, ctx.entityPath, ctx.authValue); if (r != TSS2_RC_SUCCESS) { if(has_asked_for_password){ free (ctx.authValue); } LOG_PERR ("Fapi_ChangeAuth", r); return 1; } if(has_asked_for_password){ free (ctx.authValue); } return 0; } TSS2_TOOL_REGISTER("changeauth", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_createkey.c000066400000000000000000000044231412464516500205650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* needed to conditionally free variable authValue */ static bool has_asked_for_password = false; /* Context struct used to store passed commandline parameters */ static struct cxt { char const *keyPath; char const *keyType; char const *policyPath; char *authValue; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'a': ctx.authValue = value; break; case 'p': ctx.keyPath = value; break; case 'P': ctx.policyPath = value; break; case 't': ctx.keyType = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'}, {"type", required_argument, NULL, 't'}, {"policyPath", required_argument, NULL, 'P'}, {"authValue", required_argument, NULL, 'a'}, }; return (*opts = tpm2_options_new ("a:p:P:t:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.keyPath) { fprintf (stderr, "key path missing, use --path\n"); return -1; } /* If no authValue was given, prompt the user interactively */ if (!ctx.authValue) { ctx.authValue = ask_for_password (); has_asked_for_password = true; if (!ctx.authValue){ return 1; /* User entered two different passwords */ } } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_CreateKey (fctx, ctx.keyPath, ctx.keyType, ctx.policyPath, ctx.authValue); if (r != TSS2_RC_SUCCESS){ if(has_asked_for_password){ free (ctx.authValue); } LOG_PERR ("Fapi_CreateKey", r); return 1; } if(has_asked_for_password){ free (ctx.authValue); } return 0; } TSS2_TOOL_REGISTER("createkey", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_createnv.c000066400000000000000000000063151412464516500204220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* needed to conditionally free variable authValue */ static bool has_asked_for_password = false; /* Context struct used to store passed commandline parameters */ static struct cxt { char const *nvPath; char const *nvTemplate; char *authValue; uint32_t size; char const *policyPath; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'a': ctx.authValue = value; break; case 'P': ctx.policyPath = value; break; case 'p': ctx.nvPath = value; break; case 's': if (!tpm2_util_string_to_uint32 (value, &ctx.size)) { fprintf (stderr, "%s cannot be converted to an integer or is" \ " larger than 2**32 - 1\n", value); return false; } break; case 't': ctx.nvTemplate = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'}, {"type", required_argument, NULL, 't'}, {"size", required_argument, NULL, 's'}, {"policyPath", required_argument, NULL, 'P'}, {"authValue", required_argument, NULL, 'a'}, }; return (*opts = tpm2_options_new ("P:a:p:s:t:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.nvPath) { fprintf (stderr, "No NV path provided, use --path\n"); return -1; } uint32_t size = 0; if (!ctx.size) { /* ctx.size is allowed to be zero if type is bitfield, pcr or * counter */ if (!ctx.nvTemplate || !(strstr(ctx.nvTemplate, "bitfield") || strstr(ctx.nvTemplate, "pcr") || strstr(ctx.nvTemplate, "counter"))) { fprintf (stderr, "Error: Either provide a type of \"bitfield\", "\ "pcr\" or \"counter\" with --type or provide a size > 0 with "\ "--size.\n"); return -1; } } else { size = ctx.size; } /* If no authValue was given, prompt the user interactively */ if (!ctx.authValue) { ctx.authValue = ask_for_password (); has_asked_for_password = true; if (!ctx.authValue){ return 1; /* User entered two different passwords */ } } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_CreateNv(fctx, ctx.nvPath, ctx.nvTemplate, size, ctx.policyPath, ctx.authValue); if (r != TSS2_RC_SUCCESS){ if(has_asked_for_password){ free (ctx.authValue); } LOG_PERR ("Fapi_CreateNv", r); return 1; } if(has_asked_for_password){ free (ctx.authValue); } return 0; } TSS2_TOOL_REGISTER("createnv", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_createseal.c000066400000000000000000000067661412464516500207350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* needed to conditionally free variable authValue */ static bool has_asked_for_password = false; /* Context struct used to store passed command line parameters */ static struct cxt { char const *keyPath; char const *keyType; char const *policyPath; char *authValue; char const *data; uint32_t size; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'a': ctx.authValue = value; break; case 'p': ctx.keyPath = value; break; case 'P': ctx.policyPath = value; break; case 't': ctx.keyType = value; break; case 'i': ctx.data = value; break; case 's': if (!tpm2_util_string_to_uint32 (value, &ctx.size)) { fprintf (stderr, "%s cannot be converted to an integer or is" \ " larger than 2**32 - 1\n", value); return false; } if (ctx.size == 0) { LOG_ERR("Size parameter must be larger than 0\n"); return false; } break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'}, {"type", required_argument, NULL, 't'}, {"policyPath", required_argument, NULL, 'P'}, {"authValue", required_argument, NULL, 'a'}, {"data", required_argument, NULL, 'i'}, {"size", required_argument, NULL, 's'} }; return (*opts = tpm2_options_new ("a:p:P:t:i:s:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.keyPath) { fprintf (stderr, "key path missing, use --path\n"); return -1; } if (!ctx.data && !ctx.size) { fprintf (stderr, "One of --data or --size "\ "must be used\n"); return -1; } if (ctx.data && ctx.size) { fprintf (stderr, "Only one of --data and --size "\ "can be used\n"); return -1; } /* If no authValue was given, prompt the user interactively */ if (!ctx.authValue) { ctx.authValue = ask_for_password (); has_asked_for_password = true; if (!ctx.authValue){ return 1; /* User entered two different passwords */ } } /* Read data file */ TSS2_RC r; uint8_t* data = NULL; size_t dataSize = 0; if (ctx.data) { r = open_read_and_close (ctx.data, (void**)&data, &dataSize); if (r) { return 1; } } else { if (ctx.size) { dataSize = ctx.size; } } /* Execute FAPI command with passed arguments */ r = Fapi_CreateSeal (fctx, ctx.keyPath, ctx.keyType, dataSize, ctx.policyPath, ctx.authValue, data); if (r != TSS2_RC_SUCCESS){ if(has_asked_for_password){ free (ctx.authValue); } free (data); LOG_PERR ("Fapi_CreateSeal", r); return 1; } free (data); if(has_asked_for_password){ free (ctx.authValue); } return 0; } TSS2_TOOL_REGISTER("createseal", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_decrypt.c000066400000000000000000000050541412464516500202640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *keyPath; char const *plainText; char const *cipherText; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': ctx.cipherText = value; break; case 'f': ctx.overwrite = true; break; case 'o': ctx.plainText = value; break; case 'p': ctx.keyPath = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"keyPath", required_argument, NULL, 'p'}, {"cipherText", required_argument, NULL, 'i'}, {"force" , no_argument , NULL, 'f'}, {"plainText" , required_argument, NULL, 'o'}, }; return (*opts = tpm2_options_new ("i:fo:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.keyPath) { fprintf (stderr, "No key path provided, use --keyPath\n"); return -1; } if (!ctx.cipherText) { fprintf (stderr, "No encrypted text provided, use --cipherText\n"); return -1; } if (!ctx.plainText) { fprintf (stderr, "No output file provided, use --plainText\n"); return -1; } /* Read ciphertext file */ uint8_t* cipherText; size_t cipherTextSize; TSS2_RC r = open_read_and_close (ctx.cipherText, (void**)&cipherText, &cipherTextSize); if (r){ return 1; } /* Execute FAPI command with passed arguments */ uint8_t *plainText; size_t plainTextSize; r = Fapi_Decrypt (fctx, ctx.keyPath, cipherText, cipherTextSize, &plainText, &plainTextSize); if (r != TSS2_RC_SUCCESS) { free(cipherText); LOG_PERR ("Fapi_Decrypt", r); return 1; } free(cipherText); /* Write returned data to file(s) */ r = open_write_and_close (ctx.plainText, ctx.overwrite, plainText, plainTextSize); if (r){ Fapi_Free (plainText); return 1; } Fapi_Free (plainText); return 0; } TSS2_TOOL_REGISTER("decrypt", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_delete.c000066400000000000000000000021051412464516500200460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "tools/fapi/tss2_template.h" static char *path; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'p': path = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { if (!path) { fprintf (stderr, "No path to the entity provided, use --path\n"); return -1; } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_Delete(fctx, path); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_Delete", r); return 1; } return 0; } TSS2_TOOL_REGISTER("delete", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_encrypt.c000066400000000000000000000050461412464516500202770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *keyPath; char const *plainText; char const *cipherText; bool overwrite; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'o': ctx.cipherText = value; break; case 'p': ctx.keyPath = value; break; case 'i': ctx.plainText = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"keyPath", required_argument, NULL, 'p'}, {"plainText", required_argument, NULL, 'i'}, {"cipherText", required_argument, NULL, 'o'}, {"force", no_argument , NULL, 'f'}, }; return (*opts = tpm2_options_new ("fo:p:i:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.keyPath) { fprintf (stderr, "No key path provided, use --keyPath\n"); return -1; } if (!ctx.plainText) { fprintf (stderr, "No text to encrypt provided, use --plainText\n"); return -1; } if (!ctx.cipherText) { fprintf (stderr, "No output file provided, --cipherText\n"); return -1; } /* Read plaintext file */ uint8_t *plainText; size_t plainTextSize; TSS2_RC r = open_read_and_close (ctx.plainText, (void**)&plainText, &plainTextSize); if (r){ return 1; } /* Execute FAPI command with passed arguments */ uint8_t *cipherText; size_t cipherTextSize; r = Fapi_Encrypt (fctx, ctx.keyPath, plainText, plainTextSize, &cipherText, &cipherTextSize); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_Encrypt", r); free (plainText); return 1; } free (plainText); /* Write returned data to file(s) */ r = open_write_and_close (ctx.cipherText, ctx.overwrite, cipherText, cipherTextSize); if (r) { Fapi_Free (cipherText); return 1; } Fapi_Free (cipherText); return 0; } TSS2_TOOL_REGISTER("encrypt", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_exportkey.c000066400000000000000000000045201412464516500206410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *pathOfKeyToDuplicate; char const *pathToPublicKeyOfNewParent; char const *exportedData; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'e': ctx.pathToPublicKeyOfNewParent = value; break; case 'o': ctx.exportedData = value; break; case 'p': ctx.pathOfKeyToDuplicate = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"pathToPublicKeyOfNewParent", required_argument, NULL, 'e'}, {"force", no_argument , NULL, 'f'}, {"exportedData", required_argument, NULL, 'o'}, {"pathOfKeyToDuplicate", required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("fe:o:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.exportedData) { fprintf (stderr, "exported data missing, use --output\n"); return -1; } if (!ctx.pathOfKeyToDuplicate) { fprintf (stderr, "path of key to duplicate missing, use --path\n"); return -1; } /* Execute FAPI command with passed arguments */ char *exportedData; TSS2_RC r = Fapi_ExportKey (fctx, ctx.pathOfKeyToDuplicate, ctx.pathToPublicKeyOfNewParent, &exportedData); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_ExportKey", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.exportedData, ctx.overwrite, exportedData, strlen(exportedData)); if (r){ Fapi_Free (exportedData); return 1; } Fapi_Free (exportedData); return 0; } TSS2_TOOL_REGISTER("exportkey", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_exportpolicy.c000066400000000000000000000037431412464516500213560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char *path; char *jsonPolicy; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'o': ctx.jsonPolicy = value; break; case 'p': ctx.path = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force", no_argument , NULL, 'f'}, {"path", required_argument, NULL, 'p'}, {"jsonPolicy", required_argument, NULL, 'o'}, }; return (*opts = tpm2_options_new ("fo:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path parameter is missing, pass --path\n"); return -1; } if (!ctx.jsonPolicy) { fprintf (stderr, "parameter jsonPolicy is missing, pass --jsonPolicy\n"); return -1; } /* Execute FAPI command with passed arguments */ char *jsonPolicy; TSS2_RC r = Fapi_ExportPolicy (fctx, ctx.path, &jsonPolicy); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_PolicyExport", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.jsonPolicy, ctx.overwrite, jsonPolicy, strlen(jsonPolicy)); if (r){ Fapi_Free (jsonPolicy); return 1; } Fapi_Free (jsonPolicy); return 0; } TSS2_TOOL_REGISTER("exportpolicy", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getappdata.c000066400000000000000000000037001412464516500207200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *data; char const *path; bool overwrite; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.data = value; break; case 'f': ctx.overwrite = true; break; case 'p': ctx.path = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'}, {"appData", required_argument, NULL, 'o'}, {"force" , no_argument, NULL, 'f'}, }; return (*opts = tpm2_options_new ("o:fp:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path is missing, use --path\n"); return -1; } /* Initialize return variables */ uint8_t *appData; size_t appDataSize; /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_GetAppData (fctx, ctx.path, &appData, &appDataSize); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetAppData", r); return 1; } /* Write returned data to file(s) */ if (appData && ctx.data) { r = open_write_and_close (ctx.data, ctx.overwrite, appData, appDataSize); if (r != TSS2_RC_SUCCESS) { return 1; } } /* Free allocated variables */ Fapi_Free (appData); return 0; } TSS2_TOOL_REGISTER("getappdata", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getcertificate.c000066400000000000000000000037411412464516500215750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *x509cert; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'p': ctx.path = value; break; case 'o': ctx.x509cert = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force" , no_argument , NULL, 'f'}, {"path" , required_argument, NULL, 'p'}, {"x509certData", required_argument, NULL, 'o'} }; return (*opts = tpm2_options_new ("fp:o:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path missing, use --path\n"); return -1; } if (!ctx.x509cert) { fprintf (stderr, "x509certData missing, use --x509certData\n"); return -1; } /* Execute FAPI command with passed arguments */ char *x509certData; TSS2_RC r = Fapi_GetCertificate (fctx, ctx.path, &x509certData); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetCertificate", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.x509cert, ctx.overwrite, x509certData, strlen(x509certData)); if (r){ Fapi_Free (x509certData); return 1; } Fapi_Free (x509certData); return 0; } TSS2_TOOL_REGISTER("getcertificate", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getdescription.c000066400000000000000000000037631412464516500216420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *description; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.path = value; break; case 'o': ctx.description = value; break; case 'f': ctx.overwrite = true; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path" , required_argument, NULL, 'p'}, {"description" , required_argument, NULL, 'o'}, {"force" , no_argument , NULL, 'f'}, }; return (*opts = tpm2_options_new ("o:fp:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path is missing, use --path\n"); return -1; } if (!ctx.description) { fprintf (stderr, "description is missing, use --description\n"); return -1; } /* Execute FAPI command with passed arguments */ char *description; TSS2_RC r = Fapi_GetDescription (fctx, ctx.path, &description); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetDescription", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.description, ctx.overwrite, description, strlen(description)); if (r){ Fapi_Free (description); return 1; } Fapi_Free (description); return 0; } TSS2_TOOL_REGISTER("getdescription", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getinfo.c000066400000000000000000000032251412464516500202430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char *info; bool overwrite; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'o': ctx.info = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force" , no_argument , NULL, 'f'}, /* output file */ {"info" , required_argument, NULL, 'o'} }; return (*opts = tpm2_options_new ("fo:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.info) { fprintf (stderr, "info parameter is missing, pass --info\n"); return -1; } /* Execute FAPI command with passed arguments */ char *info; TSS2_RC r = Fapi_GetInfo (fctx, &info); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetInfo", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.info, ctx.overwrite, info, strlen(info)); if (r) { Fapi_Free (info); return 1; } Fapi_Free (info); return 0; } TSS2_TOOL_REGISTER("getinfo", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getplatformcertificates.c000066400000000000000000000037221412464516500235240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *certificates; bool overwrite; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'o': ctx.certificates = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force", no_argument , NULL, 'f'}, {"certificates", required_argument, NULL, 'o'} }; return (*opts = tpm2_options_new ("fo:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.certificates) { fprintf (stderr, "certificates missing, use --certificates\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *certificates; size_t certificatesSize = 0; TSS2_RC r = Fapi_GetPlatformCertificates (fctx, &certificates, &certificatesSize); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetPlatformCertificates", r); Fapi_Free (certificates); return 1; } /* Write returned data to file(s) */ if (certificatesSize && certificatesSize > 0) { r = open_write_and_close (ctx.certificates, ctx.overwrite, certificates, certificatesSize); if (r) { Fapi_Free (certificates); return 1; } } Fapi_Free (certificates); return 0; } TSS2_TOOL_REGISTER("getplatformcertificates", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_getrandom.c000066400000000000000000000057441412464516500206000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { size_t numBytes; char *filename; bool overwrite; bool hex; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'n': { /*N.B. In theory size_t can be unsigned long, which is more than * uint32, in practice this will never happen */ uint32_t i; if (!tpm2_util_string_to_uint32 (value, &i) || i == 0) { fprintf (stderr, "%s cannot be converted to a positive integer or "\ "is larger than 2**32 - 1\n", value); return false; } ctx.numBytes = i; /* cast from uint32 to size_t */ } break; case 'f': ctx.overwrite = true; break; case 'o': ctx.filename = value; break; case 0: ctx.hex = true; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"numBytes", required_argument, NULL, 'n'}, {"force" , no_argument , NULL, 'f'}, /* output file */ {"data" , required_argument, NULL, 'o'}, {"hex", no_argument, NULL, 0} }; return (*opts = tpm2_options_new ("fn:o:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.filename) { fprintf (stderr, "No filename for data was provided, use --data\n"); return -1; } if (!ctx.numBytes) { fprintf (stderr, "No amount of bytes was provided, use --numBytes\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *data; TSS2_RC r = Fapi_GetRandom (fctx, ctx.numBytes, &data); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetRandom", r); return 1; } if (ctx.hex) { char* str = malloc (ctx.numBytes*2 + 1); if (!str) { Fapi_Free (data); LOG_ERR ("malloc(2) failed: %m\n"); return 1; } for (size_t i = 0; i #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *tpm2bPublic; char const *tpm2bPrivate; char const *policy; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'p': ctx.path = value; break; case 'u': ctx.tpm2bPublic = value; break; case 'r': ctx.tpm2bPrivate = value; break; case 'l': ctx.policy = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force" , no_argument , NULL, 'f'}, {"path" , required_argument, NULL, 'p'}, {"tpm2bPublic" , required_argument, NULL, 'u'}, {"tpm2bPrivate" , required_argument, NULL, 'r'}, {"policy" , required_argument, NULL, 'l'}, }; return (*opts = tpm2_options_new ("fp:u:r:l", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path missing, use --path\n"); return -1; } /* Check exclusive access to stdout */ int count_out = 0; if (ctx.tpm2bPublic && !strcmp (ctx.tpm2bPublic, "-")) count_out +=1; if (ctx.tpm2bPrivate && !strcmp (ctx.tpm2bPrivate, "-")) count_out +=1; if (ctx.policy && !strcmp (ctx.policy, "-")) count_out +=1; if (count_out > 1) { fprintf (stderr, "Only one of --tpm2bPublic, --tpm2bPrivate and "\ "--policy can print to - (standard output)\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *tpm2bPublic; size_t tpm2bPublicSize; uint8_t *tpm2bPrivate; size_t tpm2bPrivateSize; char *policy; TSS2_RC r = Fapi_GetTpmBlobs (fctx, ctx.path, &tpm2bPublic, &tpm2bPublicSize, &tpm2bPrivate, &tpm2bPrivateSize, &policy); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_GetTpmBlobs", r); return 1; } /* Write returned data to file(s) */ if (ctx.tpm2bPublic) { r = open_write_and_close (ctx.tpm2bPublic, ctx.overwrite, tpm2bPublic, tpm2bPublicSize); if (r) { Fapi_Free (tpm2bPublic); return 1; } } if (ctx.tpm2bPrivate) { r = open_write_and_close (ctx.tpm2bPrivate, ctx.overwrite, tpm2bPrivate, tpm2bPrivateSize); if (r) { Fapi_Free (tpm2bPublic); Fapi_Free (tpm2bPrivate); return 1; } } if (ctx.policy) { r = open_write_and_close (ctx.policy, ctx.overwrite, policy, strlen(policy)); if (r) { Fapi_Free (tpm2bPublic); Fapi_Free (tpm2bPrivate); Fapi_Free (policy); return 1; } } Fapi_Free (tpm2bPublic); Fapi_Free (tpm2bPrivate); Fapi_Free (policy); return 0; } TSS2_TOOL_REGISTER("gettpmblobs", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_import.c000066400000000000000000000033451412464516500201250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char *path; char *importData; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': ctx.importData = value; break; case 'p': ctx.path = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"importData", required_argument, NULL, 'i'}, {"path" , required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("i:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path parameter is missing, pass --path\n"); return -1; } if (!ctx.importData) { fprintf (stderr, "importData parameter is missing, pass --importData\n"); return -1; } /* Read file to import */ char *importData; TSS2_RC r = open_read_and_close (ctx.importData, (void**)&importData, NULL); if (r){ return 1; } /* Execute FAPI command with passed arguments */ r = Fapi_Import (fctx, ctx.path, importData); if (r != TSS2_RC_SUCCESS){ LOG_PERR("Fapi_Import", r); free (importData); return 1; } free (importData); return 0; } TSS2_TOOL_REGISTER("import", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_list.c000066400000000000000000000033051412464516500175620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { bool overwrite; char *searchPath; char *pathList; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'p': ctx.searchPath = value; break; case 'o': ctx.pathList = value ? value : "-"; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"force" , no_argument , NULL, 'f'}, {"searchPath", required_argument, NULL, 'p'}, {"pathList", required_argument, NULL, 'o'} }; return (*opts = tpm2_options_new ("fp:o:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { (void) fctx; /* Execute FAPI command with passed arguments */ char *pathList = NULL; TSS2_RC r = Fapi_List(fctx, ctx.searchPath ? ctx.searchPath : "", &pathList); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_List", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.pathList, ctx.overwrite, pathList, strlen(pathList)); if (r){ Fapi_Free (pathList); return 1; } Fapi_Free (pathList); return 0; } TSS2_TOOL_REGISTER("list", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_nvextend.c000066400000000000000000000047721412464516500204530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *nvPath; char const *data; char const *logData; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': ctx.data = value; break; case 'p': ctx.nvPath = value; break; case 'l': ctx.logData = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"data" , required_argument, NULL, 'i'}, {"nvPath" , required_argument, NULL, 'p'}, {"logData" , required_argument, NULL, 'l'} }; return (*opts = tpm2_options_new ("i:p:l:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.nvPath) { fprintf (stderr, "No NV path provided, use --nvPath\n"); return -1; } if (!ctx.data) { fprintf (stderr, "No file for input provided, use --data\n"); return -1; } /* Check exclusive access to stdin */ int count_in = 0; if (ctx.data && !strcmp (ctx.data, "-")) count_in +=1; if (ctx.logData && !strcmp (ctx.logData, "-")) count_in +=1; if (count_in > 1) { fprintf (stderr, "Only one of --data and --logData can read from - "\ "(standard input)\n"); return -1; } /* Read data to extend from file */ uint8_t *data; size_t data_len; TSS2_RC r = open_read_and_close (ctx.data, (void**)&data, &data_len); if (r){ return 1; } char *logData = NULL; if (ctx.logData){ TSS2_RC r = open_read_and_close (ctx.logData, (void**)&logData, 0); if (r){ free (data); return 1; } } /* Execute FAPI command with passed arguments */ r = Fapi_NvExtend(fctx, ctx.nvPath, data, data_len, logData); if (r != TSS2_RC_SUCCESS){ free (data); free (logData); LOG_PERR("Fapi_NvExtend", r); return 1; } free (data); free (logData); return 0; } TSS2_TOOL_REGISTER("nvextend", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_nvincrement.c000066400000000000000000000023241412464516500211370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "tools/fapi/tss2_template.h" /* Variable used to store passed command line parameter */ static char const *nvPath; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'p': nvPath = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"nvPath", required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!nvPath) { fprintf (stderr, "No path to the NV provided, use --nvPath\n"); return -1; } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_NvIncrement(fctx, nvPath); if (r != TSS2_RC_SUCCESS){ LOG_PERR("Fapi_NV_Increment", r); return 1; } return 0; } TSS2_TOOL_REGISTER("nvincrement", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_nvread.c000066400000000000000000000053121412464516500200660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *nvPath; char const *data; char const *logData; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'o': ctx.data = value; break; case 'p': ctx.nvPath = value; break; case 'l': ctx.logData = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"nvPath" , required_argument, NULL, 'p'}, {"force" , no_argument , NULL, 'f'}, {"data", required_argument, NULL, 'o'}, {"logData", required_argument, NULL, 'l'} }; return (*opts = tpm2_options_new ("fo:p:l:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.nvPath) { fprintf (stderr, "No NV path provided, use --nvPath\n"); return -1; } if (!ctx.data) { fprintf (stderr, "No file for output provided, use --data\n"); return -1; } /* Check exclusive access to stdout */ int count_out = 0; if (ctx.data && !strcmp (ctx.data, "-")) count_out +=1; if (ctx.logData && !strcmp (ctx.logData, "-")) count_out +=1; if (count_out > 1) { fprintf (stderr, "Only one of --data and --logData can print to - "\ "(standard output)\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *data; size_t data_len; char *logData = NULL; TSS2_RC r = Fapi_NvRead(fctx, ctx.nvPath, &data, &data_len, &logData); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_NvRead", r); return 1; } /* Write returned data to file(s) */ r = open_write_and_close (ctx.data, ctx.overwrite, data, data_len); if (r) { Fapi_Free (data); return 1; } if (ctx.logData && logData) { r = open_write_and_close (ctx.logData, ctx.overwrite, logData, strlen(logData)); if (r) { Fapi_Free (data); Fapi_Free (logData); return 1; } } Fapi_Free (data); Fapi_Free (logData); return 0; } TSS2_TOOL_REGISTER("nvread", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_nvsetbits.c000066400000000000000000000035011412464516500206260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; uint64_t bitmap; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': { uint64_t i; if (!tpm2_util_string_to_uint64 (value, &i) || i == 0) { fprintf (stderr, "%s cannot be converted to a positive integer or "\ "is larger than 2**64 - 1\n", value); return false; } ctx.bitmap = i; /* cast from uint32 to size_t */ } break; case 'p': ctx.path = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"bitmap", required_argument, NULL, 'i'}, {"nvPath" , required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("i:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "No path to the NV provided, use --nvPath\n"); return -1; } if (!ctx.bitmap) { fprintf (stderr, "No bits provided, use --bitmap [0x...]\n"); return -1; } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_NvSetBits(fctx, ctx.path, ctx.bitmap); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_NvSetBits", r); return 1; } return 0; } TSS2_TOOL_REGISTER("nvsetbits", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_nvwrite.c000066400000000000000000000033571412464516500203140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *nvPath; char const *data; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': ctx.data = value; break; case 'p': ctx.nvPath = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"data" , required_argument, NULL, 'i'}, {"nvPath" , required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("i:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.nvPath) { fprintf (stderr, "No NV path provided, use --nvPath\n"); return -1; } if (!ctx.data) { fprintf (stderr, "No file for output provided, use --data\n"); return -1; } /* Read data file */ uint8_t *data; size_t data_len; TSS2_RC r = open_read_and_close (ctx.data, (void**)&data, &data_len); if (r) { return 1; } /* Execute FAPI command with passed arguments */ r = Fapi_NvWrite(fctx, ctx.nvPath, data, data_len); if (r != TSS2_RC_SUCCESS){ free (data); LOG_PERR ("Fapi_NvWrite", r); return 1; } free (data); return 0; } TSS2_TOOL_REGISTER("nvwrite", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_pcrextend.c000066400000000000000000000053251412464516500206070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { uint32_t pcr; char const *data; char const *logData; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'x': if (!tpm2_util_string_to_uint32 (value, &ctx.pcr)) { fprintf (stderr, "%s cannot be converted to an integer or is"\ "larger than 2**32 - 1\n", value); return false; } break; case 'i': ctx.data = value; break; case 'l': ctx.logData = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"pcr" , required_argument, NULL, 'x'}, {"data", required_argument, NULL, 'i'}, {"logData", required_argument, NULL, 'l'} }; return (*opts = tpm2_options_new ("x:i:l", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.pcr) { fprintf (stderr, "No pcr provided, use --pcr\n"); return -1; } if (!ctx.data) { fprintf (stderr, "No event data provided, use --data\n"); return -1; } /* Check exclusive access to stdin */ int count_in = 0; if (ctx.data && !strcmp (ctx.data, "-")) count_in +=1; if (ctx.logData && !strcmp (ctx.logData, "-")) count_in +=1; if (count_in > 1) { fprintf (stderr, "Only one of --data and --logData can read from - "\ "(standard input)\n"); return -1; } /* Read event data and log data from file */ uint8_t *data = NULL; size_t eventDataSize; TSS2_RC r = open_read_and_close (ctx.data, (void**)&data, &eventDataSize); if (r){ return -1; } char *logData = NULL; if (ctx.logData) { r = open_read_and_close (ctx.logData, (void**)&logData, 0); if (r) { free (data); return -1; } } /* Execute FAPI command with passed arguments */ r = Fapi_PcrExtend(fctx, ctx.pcr, data, eventDataSize, logData); if (r != TSS2_RC_SUCCESS){ free (data); free (logData); LOG_PERR ("Fapi_PcrExtend", r); return 1; } free (data); free (logData); return 0; } TSS2_TOOL_REGISTER("pcrextend", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_pcrread.c000066400000000000000000000057701412464516500202370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { bool pcr_set; uint32_t pcrIndex; char const *pcrValue; char const *pcrLog; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.pcrValue = value; break; case 'x': if (!tpm2_util_string_to_uint32 (value, &ctx.pcrIndex)) { fprintf (stderr, "The PCR index must be an integer less than "\ "2**32-1\n"); return false; } ctx.pcr_set = true; break; case 'f': ctx.overwrite = true; break; case 'l': ctx.pcrLog = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"pcrIndex" , required_argument, NULL, 'x'}, {"pcrValue" , required_argument, NULL, 'o'}, {"force" , no_argument , NULL, 'f'}, {"pcrLog" , required_argument, NULL, 'l'} }; return (*opts = tpm2_options_new ("o:x:fl:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.pcr_set) { fprintf (stderr, "No PCR index provided, use --pcrIndex\n"); return -1; } /* Check exclusive access to stdout */ int count_out = 0; if (ctx.pcrValue && !strcmp (ctx.pcrValue, "-")) count_out +=1; if (ctx.pcrLog && !strcmp (ctx.pcrLog, "-")) count_out +=1; if (count_out > 1) { fprintf (stderr, "Only one of --pcrValue and --pcrLog can print to - "\ "(standard output)\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *pcrValue; size_t pcrValueSize; char *pcrLog; TSS2_RC r = Fapi_PcrRead (fctx, ctx.pcrIndex, &pcrValue, &pcrValueSize, &pcrLog); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_PcrRead", r); return 1; } /* Write returned data to file(s) */ if (ctx.pcrValue) { r = open_write_and_close (ctx.pcrValue, ctx.overwrite, pcrValue, pcrValueSize); if (r) { Fapi_Free (pcrLog); Fapi_Free (pcrValue); return 1; } } if (ctx.pcrLog) { r = open_write_and_close (ctx.pcrLog, ctx.overwrite, pcrLog, strlen(pcrLog)); if (r) { Fapi_Free (pcrLog); Fapi_Free (pcrValue); return 1; } } Fapi_Free (pcrLog); Fapi_Free (pcrValue); return 0; } TSS2_TOOL_REGISTER("pcrread", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_provision.c000066400000000000000000000026471412464516500206470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char *authValueEh; char *authValueSh; char *authValueLockout; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'E': ctx.authValueEh = value; break; case 'S': ctx.authValueSh = value; break; case 'L': ctx.authValueLockout = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"authValueEh", required_argument, NULL, 'E'}, {"authValueSh", required_argument, NULL, 'S'}, {"authValueLockout", required_argument, NULL, 'L'}, }; return (*opts = tpm2_options_new ("E:S:L", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_Provision (fctx, ctx.authValueEh, ctx.authValueSh, ctx.authValueLockout); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_Provision", r); return 1; } return 0; } TSS2_TOOL_REGISTER("provision", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_quote.c000066400000000000000000000145711412464516500177530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { uint32_t *pcrList; size_t pcrListSize; char const *keyPath; char const *qualifyingData; char const *quoteInfo; char const *pcrLog; char const *signature; char const *certificate; bool overwrite; } ctx; /** * Split the comma separated input, parse each token as number, * put the numbers in the array output. Allocate memory for * output to hold the numbers. * * On failure returns false and output is not allocated. * On success the caller frees output. */ static inline bool extract_pcrs(char *input, uint32_t **output, size_t *list_size) { size_t size = 1; char *temp = input; while ((temp = strchr (temp+1, ','))) size++; *output = malloc (sizeof(uint32_t) * (size)); if (!*output) { fprintf (stderr, "malloc failed: %m\n"); return false; } char *x = strtok_r (input, ",", &temp); if (!tpm2_util_string_to_uint32(x, output[0])) { fprintf (stderr, "%s cannot be used as PCR\n", x); free (*output); return false; } size = 0; while ((x = strtok_r (NULL, ",", &temp))) { if (!tpm2_util_string_to_uint32(x, &(*output)[++size])) { fprintf (stderr, "%s cannot be used as PCR\n", x); free (*output); return false; } } *list_size = size+1; return true; } /* Parse command line parameters */ static bool on_option(char key, char *value) { (void)value; switch (key) { case 'x': return extract_pcrs(value, &ctx.pcrList, &ctx.pcrListSize); case 'Q': ctx.qualifyingData = value; break; case 'l': ctx.pcrLog = value; break; case 'f': ctx.overwrite = true; break; case 'p': ctx.keyPath = value; break; case 'q': ctx.quoteInfo = value; break; case 'o': ctx.signature = value; break; case 'c': ctx.certificate = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"pcrList" , required_argument, NULL, 'x'}, {"keyPath" , required_argument, NULL, 'p'}, {"qualifyingData", required_argument, NULL, 'Q'}, {"quoteInfo" , required_argument, NULL, 'q'}, {"signature" , required_argument, NULL, 'o'}, {"pcrLog" , required_argument, NULL, 'l'}, {"certificate" , required_argument, NULL, 'c'}, {"force" , no_argument , NULL, 'f'} }; return (*opts = tpm2_options_new ("x:Q:l:fp:q:o:c:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.pcrList) { fprintf (stderr, "No PCRs were chosen, use --pcrList\n"); return -1; } if (!ctx.keyPath) { fprintf (stderr, "No key path provided, use --keyPath\n"); free (ctx.pcrList); return -1; } if (!ctx.quoteInfo) { fprintf (stderr, "No quoteInfo provided, use --quoteInfo\n"); free (ctx.pcrList); return -1; } if (!ctx.signature) { fprintf (stderr, "No signature provided, use --signature\n"); free (ctx.pcrList); return -1; } /* Check exclusive access to stdout */ int count_out = 0; if (ctx.quoteInfo && !strcmp (ctx.quoteInfo, "-")) count_out +=1; if (ctx.pcrLog && !strcmp (ctx.pcrLog, "-")) count_out +=1; if (ctx.signature && !strcmp (ctx.signature, "-")) count_out +=1; if (ctx.certificate && !strcmp (ctx.certificate, "-")) count_out +=1; if (count_out > 1) { fprintf (stderr, "Only one of --quoteInfo, --pcrLog, --signature and "\ "--certificate can print to - (standard output)\n"); free (ctx.pcrList); return -1; } /* Read qualifyingData file */ TSS2_RC r; uint8_t *qualifyingData = NULL; size_t qualifyingDataSize = 0; if (ctx.qualifyingData) { r = open_read_and_close (ctx.qualifyingData, (void*)&qualifyingData, &qualifyingDataSize); if (r) { free (ctx.pcrList); return 1; } } /* Execute FAPI command with passed arguments */ uint8_t *signature; size_t signatureSize; char *quoteInfo, *pcrLog = NULL, *certificate = NULL; r = Fapi_Quote (fctx, ctx.pcrList, ctx.pcrListSize, ctx.keyPath, NULL, qualifyingData, qualifyingDataSize, "eInfo, &signature, &signatureSize, &pcrLog, &certificate); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_Quote", r); free (ctx.pcrList); free (qualifyingData); return 1; } free (ctx.pcrList); free (qualifyingData); /* Write returned data to file(s) */ if (ctx.quoteInfo && quoteInfo) { r = open_write_and_close (ctx.quoteInfo, ctx.overwrite, quoteInfo, strlen(quoteInfo)); if (r) { Fapi_Free (quoteInfo); Fapi_Free (pcrLog); Fapi_Free (signature); Fapi_Free (certificate); return 1; } } Fapi_Free (quoteInfo); if (ctx.pcrLog && pcrLog) { r = open_write_and_close (ctx.pcrLog, ctx.overwrite, pcrLog, strlen(pcrLog)); if (r) { Fapi_Free (pcrLog); Fapi_Free (signature); Fapi_Free (certificate); return 1; } } Fapi_Free (pcrLog); if (ctx.signature && signature) { r = open_write_and_close (ctx.signature, ctx.overwrite, signature, signatureSize); if (r) { Fapi_Free (signature); Fapi_Free (certificate); return 1; } } Fapi_Free (signature); if (ctx.certificate && certificate) { r = open_write_and_close (ctx.certificate, ctx.overwrite, certificate, strlen(certificate)); if (r) { Fapi_Free (certificate); return 1; } } Fapi_Free (certificate); return 0; } TSS2_TOOL_REGISTER("quote", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_setappdata.c000066400000000000000000000033661412464516500207440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *appData; char const *path; } ctx; /* Parse commandline parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': ctx.appData = value; break; case 'p': ctx.path = value; break; } return true; } /* Define possible commandline parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"appData", required_argument, NULL, 'i'}, {"path", required_argument, NULL, 'p'}, }; return (*opts = tpm2_options_new ("i:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path is missing, use --path\n"); return -1; } /* Read appData from file */ TSS2_RC r; uint8_t* appData = NULL; size_t appDataSize = 0; if (ctx.appData) { r = open_read_and_close (ctx.appData, (void**)&appData, &appDataSize); if (r) { return 1; } } /* Execute FAPI command with passed arguments */ r = Fapi_SetAppData (fctx, ctx.path, appData, appDataSize); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_SetAppData", r); free(appData); return 1; } free(appData); return 0; } TSS2_TOOL_REGISTER("setappdata", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_setcertificate.c000066400000000000000000000033611412464516500216070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *x509cert; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.path = value; break; case 'i': ctx.x509cert = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path" , required_argument, NULL, 'p'}, {"x509certData", required_argument, NULL, 'i'} }; return (*opts = tpm2_options_new ("p:i", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path missing, use --path\n"); return -1; } /* Read x509 certificate from file */ TSS2_RC r; char* x509certData = NULL; size_t x509certSize; if (ctx.x509cert) { r = open_read_and_close (ctx.x509cert, (void**)&x509certData, &x509certSize); if (r) { return 1; } } /* Execute FAPI command with passed arguments */ r = Fapi_SetCertificate (fctx, ctx.path, x509certData); if (r != TSS2_RC_SUCCESS){ free (x509certData); LOG_PERR("Fapi_SetCertificate", r); return 1; } free (x509certData); return 0; } TSS2_TOOL_REGISTER("setcertificate", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_setdescription.c000066400000000000000000000031201412464516500216410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *description; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'i': if (value && strlen (value) > 1023) { fprintf (stderr, "The description can be at most 1023 octets\n"); return false; } ctx.description = value; break; case 'p': ctx.path = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"description", required_argument, NULL, 'i'}, {"path" , required_argument, NULL, 'p'} }; return (*opts = tpm2_options_new ("i:p:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path is missing, use --path\n"); return -1; } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_SetDescription (fctx, ctx.path, ctx.description); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_SetDescription", r); return 1; } return 0; } TSS2_TOOL_REGISTER("setdescription", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_sign.c000066400000000000000000000102641412464516500175510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *keyPath; char const *digest; char const *signature; char const *publicKey; char const *certificate; bool overwrite; char const *padding; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.certificate = value; break; case 'd': ctx.digest = value; break; case 'f': ctx.overwrite = true; break; case 'p': ctx.keyPath = value; break; case 'k': ctx.publicKey = value; break; case 'o': ctx.signature = value; break; case 's': ctx.padding = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"keyPath", required_argument, NULL, 'p'}, {"padding", required_argument, NULL, 's'}, {"digest", required_argument, NULL, 'd'}, {"signature", required_argument, NULL, 'o'}, {"publicKey", required_argument, NULL, 'k'}, {"force", no_argument , NULL, 'f'}, {"certificate", required_argument, NULL, 'c'}, }; return (*opts = tpm2_options_new ("c:d:fp:k:o:s:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.digest) { fprintf (stderr, "digest missing, use --digest\n"); return -1; } if (!ctx.keyPath) { fprintf (stderr, "key path missing, use --keyPath\n"); return -1; } if (!ctx.signature) { fprintf (stderr, "signature missing, use --signature\n"); return -1; } /* Check exclusive access to stdout */ int count_out = 0; if (ctx.certificate && !strcmp (ctx.certificate, "-")) count_out +=1; if (ctx.signature && !strcmp (ctx.signature, "-")) count_out +=1; if (ctx.publicKey && !strcmp (ctx.publicKey, "-")) count_out +=1; if (count_out > 1) { fprintf (stderr, "Only one of --certificate, --signature and "\ "--publicKey can print to - (standard output)\n"); return -1; } /* Read data needed to create signature */ uint8_t *digest, *signature; size_t digestSize, signatureSize; char *publicKey, *certificate = NULL; TSS2_RC r = open_read_and_close (ctx.digest, (void**)&digest, &digestSize); if (r){ return 1; } /* Execute FAPI command with passed arguments */ r = Fapi_Sign (fctx, ctx.keyPath, ctx.padding, digest, digestSize, &signature, &signatureSize, &publicKey, &certificate); if (r != TSS2_RC_SUCCESS) { LOG_PERR ("Fapi_Sign", r); free (digest); return 1; } free (digest); /* Write returned data to file(s) */ if (ctx.certificate && certificate && strlen(certificate)) { r = open_write_and_close (ctx.certificate, ctx.overwrite, certificate, strlen(certificate)); if (r) { Fapi_Free (certificate); Fapi_Free (signature); Fapi_Free (publicKey); return 1; } } Fapi_Free (certificate); if (ctx.signature && signature) { r = open_write_and_close (ctx.signature, ctx.overwrite, signature, signatureSize); if (r) { Fapi_Free (signature); Fapi_Free (publicKey); return 1; } } Fapi_Free (signature); if (ctx.publicKey && publicKey) { r = open_write_and_close (ctx.publicKey, ctx.overwrite, publicKey, strlen(publicKey)); if (r) { Fapi_Free (publicKey); return 1; } } Fapi_Free (publicKey); return 0; } TSS2_TOOL_REGISTER("sign", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_template.c000066400000000000000000000511521412464516500204250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tools/fapi/tss2_template.h" #include "lib/config.h" #include "lib/tpm2_alg_util.h" #define READ_SIZE 1024 /* needed by tpm2_util and tpm2_option functions */ bool output_enabled = false; static struct termios old; /* When the program is interrupted during callbacks, * restore the old termios state (with ICANON and ECHO) */ static void signal_termio_restore(__attribute__((unused)) int signumber) { tcsetattr (STDIN_FILENO, TCSANOW, &old); } /* adapted from lib/tpm2_options.c for tss2 */ static bool execute_man(char *prog_name, bool show_errors) { pid_t pid; int status; if ((pid = fork()) < 0) { LOG_ERR("Could not fork process to execute man, error: %s", strerror(errno)); return false; } if (pid == 0) { if (!show_errors) { /* redirect manpager errors to stderr */ int fd = open("/dev/null", O_WRONLY); if (fd < 0) { LOG_ERR("Could not open /dev/null"); return false; } dup2(fd, 2); close(fd); } char *manpage = basename(prog_name); execlp("man", "man", manpage, NULL); } else { if (waitpid(pid, &status, 0) == -1) { LOG_ERR("Waiting for child process that executes man failed, error:" " %s", strerror(errno)); return false; } return WEXITSTATUS(status) == 0; } return true; } /* adapted from lib/tpm2_options.c for tss2 */ static tpm2_option_code tss2_handle_options ( int argc, char **argv, tpm2_options **tool_opts) { tpm2_option_code rc = tpm2_option_code_err; bool show_help = false, manpager = true, explicit_manpager = false; struct option long_options [] = { {"help" , optional_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'} }; tpm2_options *opts = tpm2_options_new("h::v", ARRAY_LEN(long_options), long_options, NULL, NULL, 0); if (!opts) { return tpm2_option_code_err; } /* Get the options from the tool */ if (!*tool_opts || !(*tool_opts)->callbacks.on_opt) { fprintf (stderr, "Unknown option found\n"); goto out; } tpm2_option_handler on_opt = (*tool_opts)->callbacks.on_opt; tpm2_arg_handler on_arg = (*tool_opts)->callbacks.on_arg; if (!tpm2_options_cat (tool_opts, opts)) goto out; (*tool_opts)->callbacks.on_opt = on_opt; (*tool_opts)->callbacks.on_arg = on_arg; /* Parse the options, calling the tool callback if unknown */ int c; while ((c = getopt_long (argc, argv, (*tool_opts)->short_opts, (*tool_opts)->long_opts, NULL)) != -1) { switch (c) { case 'h': show_help = true; if (argv[optind]) { if (!strcmp(argv[optind], "man")) { manpager = true; explicit_manpager = true; optind++; } else if (!strcmp(argv[optind], "no-man")) { manpager = false; optind++; } else { show_help=false; fprintf (stderr, "Unknown help argument, got: \"%s\"\n", argv[optind]); } } goto out; break; case 'v': { char *prog_name = strdup (argv[0]); if (!prog_name) { fprintf (stderr, "Not enough memory\n"); goto out; } printf("tool=\"%s\" version=\"%s\"\n", basename (prog_name), VERSION); free(prog_name); } rc = tpm2_option_code_stop; goto out; case '?': goto out; default: if (!(*tool_opts)->callbacks.on_opt(c, optarg)) goto out; } } char **tool_args = &argv[optind]; int tool_argc = argc - optind; /* have args and no handler, error condition */ if (tool_argc && !(*tool_opts)->callbacks.on_arg) { char *prog_name = strdup (argv[0]); if (!prog_name) { fprintf (stderr, "Not enough memory\n"); goto out; } fprintf (stderr, "Got arguments but %s takes no arguments\n", basename (prog_name)); free (prog_name); goto out; } else if (tool_argc && (*tool_opts)->callbacks.on_arg && !(*tool_opts)->callbacks.on_arg(tool_argc, tool_args)) { goto out; } rc = tpm2_option_code_continue; out: /* * If help output is selected via -h or indicated by an error that help * output is desirable, show it. * * However, 3 conditions are possible: * 1. Try manpager and success -- done, no need to show short help output. * 2. Try manpager and failure -- show short help output. * 3. Do not use manpager -- show short help output. * */ if (show_help) { if (!manpager || !execute_man (argv[0], explicit_manpager)) { tpm2_print_usage (argv[0], *tool_opts); } rc = tpm2_option_code_stop; } tpm2_options_free (opts); return rc; } char *password = NULL; TSS2_RC auth_callback( #ifdef FAPI_3_0 char const *objectPath, char const *description, char const **auth, void *userdata) { #else /* FAPI_3_0 */ __attribute__((unused)) FAPI_CONTEXT *fapi_context, char const *description, char **auth, void *userdata) { const char *objectPath = "object"; #endif /* FAPI_3_0 */ if (password != NULL) { free(password); password = NULL; } struct termios new; tcgetattr (STDIN_FILENO, &old); new = old; new.c_lflag &= ~(ICANON | ECHO); if (userdata) { printf("%s:", (const char *) userdata); } else { printf ("Authorize %s \"%s\": ", objectPath, description); } tcsetattr (STDIN_FILENO, TCSANOW, &new); size_t input_size = 0; struct sigaction signal_action; memset (&signal_action, 0, sizeof signal_action); signal_action.sa_handler = signal_termio_restore; sigaction (SIGTERM, &signal_action, NULL); sigaction (SIGINT, &signal_action, NULL); ssize_t getline_ret = getline (&password, &input_size, stdin); /* It is intentional, that auth can contain null bytes, and from * FAPI’s perspective these terminate the password. */ tcsetattr (STDIN_FILENO, TCSANOW, &old); signal_action.sa_handler = SIG_DFL; sigaction (SIGTERM, &signal_action, NULL); sigaction (SIGINT, &signal_action, NULL); printf ("\n"); if (getline_ret == -1) { fprintf (stderr, "getline() failed: %m\n"); free (password); password = NULL; return TSS2_TCTI_RC_GENERAL_FAILURE; } password[getline_ret - 1] = '\0'; #ifdef FAPI_3_0 *auth = password; #else /* FAPI_3_0 */ *auth = strdup(password); #endif /* FAPI_3_0 */ return TSS2_RC_SUCCESS; } uint8_t *input_signature = NULL; TSS2_RC sign_callback( #ifdef FAPI_3_0 char const *objectPath, #else /* FAPI_3_0 */ __attribute__((unused)) FAPI_CONTEXT *fapi_context, #endif /* FAPI_3_0 */ char const *description, char const *publicKey, char const *publicKeyHint, uint32_t hashAlg, uint8_t const *dataToSign, size_t dataToSignSize, #ifdef FAPI_3_0 uint8_t const **signature, #else /* FAPI_3_0 */ uint8_t **signature, #endif /* FAPI_3_0 */ size_t *signatureSize, void *userData) { if (input_signature != NULL) { free(input_signature); input_signature = NULL; } int rc; char path[READ_SIZE]; char publicKeyHintStr[READ_SIZE]; if (userData) { printf("%s:", (const char *) userData); } else { const char *hashAlgName = tpm2_alg_util_algtostr(hashAlg, tpm2_alg_util_flags_hash); int cpy_size = 0; if (strlen(publicKeyHint) > 0) { const char* tmp = "the key corresponding to the key hint \"%s\" and"; cpy_size = strlen(tmp) - 2 /* remove replaced %s */ + strlen(publicKeyHint); rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp, publicKeyHint); if (rc != cpy_size){ fprintf (stderr, "Command snprintf failed with %d\n", rc); return TSS2_FAPI_RC_GENERAL_FAILURE; } } else { const char* tmp = "the key corresponding to the fingerprint \"%s\" and"; char publicKeyHintTmp[READ_SIZE]; rc = tpm2_pem_encoded_key_to_fingerprint(publicKey, publicKeyHintTmp); if (rc != true){ fprintf (stderr, "Error getting the fingerprint of the "\ "PEM-encoded public key\n"); return TSS2_FAPI_RC_GENERAL_FAILURE; } cpy_size = strlen(tmp) - 2 /* remove replaced %s */ + strlen(publicKeyHintTmp); rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp, publicKeyHintTmp); if (rc != cpy_size){ fprintf (stderr, "Command snprintf failed with %d\n", rc); return TSS2_FAPI_RC_GENERAL_FAILURE; } } #ifdef FAPI_3_0 printf("%s: Authorize usage of %s by signing the nonce with %s the hash "\ "algorithm \"%s\".\n", description, objectPath, publicKeyHintStr, hashAlgName); #else /* FAPI_3_0 */ printf("%s: Authorize usage of the key by signing the nonce with %s the "\ "hash algorithm \"%s\".\n", description, publicKeyHintStr, hashAlgName); #endif /* FAPI_3_0 */ } printf("Filename for nonce output: "); rc = tpm2_safe_read_from_stdin(READ_SIZE, path); if (rc != true){ fprintf (stderr, "Please enter a valid file path\n"); return TSS2_FAPI_RC_GENERAL_FAILURE; } rc = open_write_and_close(path, true, dataToSign, dataToSignSize); if (rc) { fprintf (stderr, "Could not write to file: %s\n", path); return TSS2_FAPI_RC_GENERAL_FAILURE; } printf("Filename for signature input: "); rc = tpm2_safe_read_from_stdin(READ_SIZE, path); if (rc != true){ fprintf (stderr, "Please enter a valid file path\n"); return TSS2_FAPI_RC_GENERAL_FAILURE; } size_t input_signatureSize; rc = open_read_and_close (path, (void**)&input_signature, &input_signatureSize); if (rc) { fprintf (stderr, "Could not read from file path: %s\n", path); return TSS2_FAPI_RC_GENERAL_FAILURE; } *signature = input_signature; *signatureSize = input_signatureSize; return TSS2_RC_SUCCESS; } TSS2_RC branch_callback( #ifdef FAPI_3_0 char const *objectPath, #else /* FAPI_3_0 */ __attribute__((unused)) FAPI_CONTEXT *fapi_context, #endif /* FAPI_3_0 */ char const *description, char const **branchNames, size_t numBranches, size_t *selectedBranch, __attribute__((unused)) void *userData) { #ifdef FAPI_3_0 printf ("Select a branch for %s \"%s\"\n", objectPath, description); #else /* FAPI_3_0 */ printf ("Select a branch for object \"%s\"\n", description); #endif /* FAPI_3_0 */ for (size_t i = 0; i < numBranches; i++) { printf ("%4zu %s\n", i + 1, branchNames[i]); } while (1) { printf ("Your choice: "); if (scanf ("%zu", selectedBranch) != EOF) { while (getchar () != '\n'); /* Consume all remaining input */ if (*selectedBranch > numBranches || *selectedBranch < 1) { fprintf (stderr, "The entered integer must be positive and "\ "less than %zu.\n", numBranches + 1); } else { (*selectedBranch)--; /* the user display/choice is always +1 */ return TSS2_RC_SUCCESS; } } else { fprintf (stderr, "No number received, but EOF.\n"); return TSS2_FAPI_RC_GENERAL_FAILURE; } } } static FAPI_CONTEXT* ctx_init(char const * uri) { FAPI_CONTEXT* ret; const unsigned int rval = Fapi_Initialize(&ret, uri); if (rval != TSS2_RC_SUCCESS){ LOG_PERR("Fapi_Initialize", rval); return NULL; } return ret; } /* * Build a list of the TSS2 tools linked into this executable */ #ifndef TSS2_TOOLS_MAX #define TSS2_TOOLS_MAX 1024 #endif static const tss2_tool *tools[TSS2_TOOLS_MAX]; static unsigned tool_count; void tss2_tool_register(const tss2_tool *tool) { if (tool_count < TSS2_TOOLS_MAX) { tools[tool_count++] = tool; } else { LOG_ERR("Over tool count"); abort(); } } static const char *tss2_tool_name(const char *arg) { const char *name = rindex(arg, '/'); if (name) { name++; // skip the '/' } else { name = arg; // use the full executable name as is } if (strncmp(name, "tss2_", 5) == 0) { name += 5; } return name; } static const tss2_tool *tss2_tool_lookup(int *argc, char ***argv) { // find the executable name in the path // and skip "tss2_" prefix if it is present const char *name = tss2_tool_name((*argv)[0]); // if this was invoked as 'tss2', then try again with the second argument if (strcmp(name, "tss2") == 0) { if (--(*argc) == 0) { return NULL; } (*argv)++; name = tss2_tool_name((*argv)[0]); } // search the tools array for a matching name for(unsigned i = 0 ; i < tool_count ; i++) { const tss2_tool * const tool = tools[i]; if (!tool || !tool->name) { continue; } if (strcmp(name, tool->name) == 0) { return tool; } } // not found? should print a table of the tools return NULL; } /* * This program is a template for TPM2 tools that use the FAPI. It does * nothing more than parsing command line options that allow the caller to * specify which FAPI function to call. */ int main(int argc, char *argv[]) { /* get rid of: * other write + read + execute (7) */ umask(0007); const tss2_tool * const tool = tss2_tool_lookup(&argc, &argv); if (!tool) { LOG_ERR("%s: unknown tool. Available tss2 commands:\n", argv[0]); for(unsigned i = 0 ; i < tool_count ; i++) { fprintf(stderr, "%s\n", tools[i]->name); } return EXIT_FAILURE; } tpm2_options *tool_opts = NULL; if (tool->onstart && !tool->onstart (&tool_opts)) { fprintf (stderr,"error retrieving tool options\n"); return 1; } int ret = 1; tpm2_option_code rc = tss2_handle_options (argc, argv, &tool_opts); if (rc != tpm2_option_code_continue) { ret = rc == tpm2_option_code_err ? 1 : 0; goto free_opts; } FAPI_CONTEXT *fctx = ctx_init (NULL); if (!fctx) goto free_opts; TSS2_RC r = Fapi_SetAuthCB (fctx, auth_callback, NULL); if (r != TSS2_RC_SUCCESS) { fprintf (stderr, "Fapi_SetAuthCB returned %u\n", r); Fapi_Finalize (&fctx); goto free_opts; } r = Fapi_SetSignCB (fctx, sign_callback, NULL); if (r != TSS2_RC_SUCCESS) { fprintf (stderr, "Fapi_SetSignCB returned %u\n", r); Fapi_Finalize (&fctx); goto free_opts; } r = Fapi_SetBranchCB (fctx, branch_callback, NULL); if (r != TSS2_RC_SUCCESS) { fprintf (stderr, "Fapi_SetBranchCB returned %u\n", r); Fapi_Finalize (&fctx); goto free_opts; } /* * Call the specific tool, all tools implement this function instead of * 'main'. * rc 1 = failure * rc 0 = success * rc -1 = show usage */ ret = tool->onrun(fctx); if (ret < 0) { tpm2_print_usage(argv[0], tool_opts); ret = 1; } if (tool->onexit) { tool->onexit(); } /* * Cleanup contexts & memory allocated for the modified argument vector * passed to execute_tool. */ Fapi_Finalize (&fctx); free_opts: if (tool_opts) tpm2_options_free (tool_opts); free (password); if (ret == 0){ free (input_signature); } exit(ret); } int open_write_and_close(const char* path, bool overwrite, const void *output, size_t output_len) { size_t length = 0; if (output_len){ length = output_len; } if (!path || !strcmp(path, "-")) { if (-1 == write (STDOUT_FILENO, output, length)) { fprintf (stderr, "write(2) to stdout failed: %m\n"); return 1; } return 0; } int oflags = O_CREAT | O_WRONLY | O_TRUNC ; if (!overwrite) { oflags |= O_EXCL; } int fileno = open (path, oflags, S_IWUSR | S_IRUSR); if (fileno == -1) { if (errno == EEXIST) { fprintf (stderr, "open(2) %s failed: %m\n", path); } return 1; } ssize_t bytes_written = write (fileno, output, length); if (bytes_written == -1) { fprintf (stderr, "write(2) %s failed: %m\n", path); close (fileno); return 1; } if (bytes_written - length) { fprintf (stderr, "write(2) could not write the whole file, deleting "\ "%s\n", path); unlink (path); close (fileno); return 1; } if (close (fileno)) { fprintf (stderr, "close(2) %s failed: %m\n", path); return 1; } return 0; } int open_read_and_close (const char *path, void **input, size_t *size) { if (!path || !strcmp(path, "-")) { size_t data_consumed = 0, buffer_size = 1024, data_read; *input = malloc (buffer_size + 1); if (!*input) { fprintf (stderr, "malloc(2) failed: %m\n"); return 1; } while ((data_read = read (STDIN_FILENO, *input + data_consumed, 1024))){ data_consumed += data_read; if (data_read < 1024) /* EOF reached */ break; buffer_size += 1024; *input = realloc (*input, buffer_size + 1); if (!*input) { fprintf (stderr, "realloc(3) failed: %m\n"); return 1; } } if (size) *size = data_consumed; ((char*)(*input))[data_consumed] = 0; return 0; } int fileno = open (path, O_RDONLY); if (fileno == -1) { fprintf (stderr, "Opening %s failed: %m\n", path); return 1; } struct stat stat_; errno = 0; if (fstat (fileno, &stat_)) { printf("\nfstat error: [%s]\n",strerror(errno)); close(fileno); return 1; } if (size) *size = stat_.st_size; *input = malloc (stat_.st_size + 1); if (!*input) { fprintf (stderr, "malloc(2) failed: %m\n"); close (fileno); return 1; } if (-1 == read (fileno, *input, stat_.st_size)) { fprintf (stderr, "read(2) %s failed with: %m\n", path); free (*input); close (fileno); return 1; } ((char*)(*input))[stat_.st_size] = '\0'; if (close (fileno)) { fprintf (stderr, "Error close(2) %s: %m\n", path); free (*input); return 1; } return 0; } char* ask_for_password() { #ifdef FAPI_3_0 const char *pw; #else /* FAPI_3_0 */ char *pw; #endif /* FAPI_3_0 */ char *ret_pw = NULL; if (auth_callback (NULL, NULL, &pw, "New password")) goto error; #ifdef FAPI_3_0 ret_pw = strdup(pw); if (!ret_pw) { fprintf (stderr, "OOM\n"); return NULL; } #else /* FAPI_3_0 */ ret_pw = pw; #endif /* FAPI_3_0 */ if (auth_callback (NULL, NULL, &pw, "Re-enter new password")) goto error; bool eq = !strcmp (ret_pw, pw); #ifndef FAPI_3_0 free(pw); #endif if (!eq) { fprintf (stderr, "Passwords do not match.\n"); goto error; } return ret_pw; error: if (ret_pw) free(ret_pw); return NULL; } void LOG_PERR(const char *func, TSS2_RC rc) { fprintf (stderr, "%s(0x%X) - %s\n", func, rc, Tss2_RC_Decode(rc)); } void LOG_ERR(const char *format, ...) { va_list arg; va_start (arg, format); vfprintf (stderr, format, arg); va_end (arg); } tpm2-tools-5.2/tools/fapi/tss2_template.h000066400000000000000000000037411412464516500204330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef TSS2_TEMPLATE_H #define TSS2_TEMPLATE_H #include #include #include "lib/tpm2_options.h" #include "lib/tpm2_util.h" #define Fapi_Free(x) free(x) /** * An optional interface for tools to specify what options they support. * They are concatenated with main's options and passed to getopt_long. * @param opts * The callee can choose to set *opts to a tpm_options pointer allocated * via tpm2_options_new(). Setting *opts to NULL is not an error, and * Indicates that no options are specified by the tool. * * @return * True on success, false on error. */ typedef bool (*tss2_tool_onstart_t)(tpm2_options **opts); /** * This is the main interface for tools, after tcti and fapi initialization * is performed. * @param fctx * The fapi api context. * @return * 0 on success * 1 on failure * -1 to show usage */ typedef int (*tss2_tool_onrun_t)(FAPI_CONTEXT *fctx); /** * Called when the tool is exiting, useful for cleanup. */ typedef void (*tss2_tool_onexit_t)(void); typedef struct { const char * name; tss2_tool_onstart_t onstart; tss2_tool_onrun_t onrun; tss2_tool_onexit_t onexit; } tss2_tool; void tss2_tool_register(const tss2_tool * tool); #define TSS2_TOOL_REGISTER(tool_name,tool_onstart,tool_onrun,tool_onexit) \ static const tss2_tool tool = { \ .name = tool_name, \ .onstart = tool_onstart, \ .onrun = tool_onrun, \ .onexit = tool_onexit, \ }; \ static void \ __attribute__((__constructor__)) \ __attribute__((__used__)) \ _tss2_tool_init(void) \ { \ tss2_tool_register(&tool); \ } TSS2_RC policy_auth_callback(FAPI_CONTEXT*, char const*, char**, void*); int open_write_and_close(const char *path, bool overwrite, const void* output, size_t output_len); int open_read_and_close(const char *path, void **input, size_t *size); char* ask_for_password(); void LOG_PERR(const char *func, TSS2_RC rc); void LOG_ERR(const char *format, ...); #endif /* TSS2_TEMPLATE_H */ tpm2-tools-5.2/tools/fapi/tss2_unseal.c000066400000000000000000000035051412464516500201000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *path; char const *data; bool overwrite; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'f': ctx.overwrite = true; break; case 'p': ctx.path = value; break; case 'o': ctx.data = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"path", required_argument, NULL, 'p'}, {"data", required_argument, NULL, 'o'}, {"force", no_argument, NULL, 'f'} }; return (*opts = tpm2_options_new ("p:o:f", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.path) { fprintf (stderr, "path to the sealed data missing, use --path\n"); return -1; } /* Execute FAPI command with passed arguments */ uint8_t *data; size_t size; TSS2_RC r = Fapi_Unseal (fctx, ctx.path, &data, &size); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_Unseal", r); return 1; } /* Write returned data to file(s) */ if (ctx.data && data) { r = open_write_and_close (ctx.data, ctx.overwrite, data, size); if (r) { Fapi_Free (data); return 1; } } Fapi_Free (data); return 0; } TSS2_TOOL_REGISTER("unseal", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_verifyquote.c000066400000000000000000000102201412464516500211630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char *publicKeyPath; char const *qualifyingData; char const *quoteInfo; char const *signature; char const *pcrLog; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'Q': ctx.qualifyingData = value; break; case 'l': ctx.pcrLog = value; break; case 'q': ctx.quoteInfo = value; break; case 'k': ctx.publicKeyPath = value; break; case 'i': ctx.signature = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"publicKeyPath", required_argument, NULL, 'k'}, {"qualifyingData", required_argument, NULL, 'Q'}, {"quoteInfo", required_argument, NULL, 'q'}, {"signature", required_argument, NULL, 'i'}, {"pcrLog", required_argument, NULL, 'l'} }; return (*opts = tpm2_options_new ("k:Q:q:i:l:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.quoteInfo) { fprintf (stderr, "quote info parameter not provided, use "\ "--quoteInfo\n"); return -1; } if (!ctx.publicKeyPath) { fprintf (stderr, "publicKeyPath parameter not provided, use "\ "--publicKeyPath\n"); return -1; } if (!ctx.signature) { fprintf (stderr, "signature parameter not provided, use"\ " --signature\n"); return -1; } /* Check exclusive access to stdin */ int count_in = 0; if (ctx.qualifyingData && !strcmp (ctx.qualifyingData, "-")) count_in +=1; if (ctx.signature && !strcmp (ctx.signature, "-")) count_in +=1; if (ctx.quoteInfo && !strcmp (ctx.quoteInfo, "-")) count_in +=1; if (ctx.pcrLog && !strcmp (ctx.pcrLog, "-")) count_in +=1; if (count_in > 1) { fprintf (stderr, "Only one of --qualifyingData, --signature, "\ " --quoteInfo and --pcrLog can read from - (standard input)\n"); return -1; } /* Read qualifyingData, signature, quoteInfo and pcrLog from file */ TSS2_RC r; uint8_t *qualifyingData = NULL; size_t qualifyingDataSize = 0; if (ctx.qualifyingData) { r = open_read_and_close (ctx.qualifyingData, (void**)&qualifyingData, &qualifyingDataSize); if (r) { return -1; } } uint8_t *signature = NULL; size_t signatureSize = 0; if (ctx.signature) { r = open_read_and_close (ctx.signature, (void**)&signature, &signatureSize); if (r) { free (qualifyingData); return -1; } } char *quoteInfo = NULL; if (ctx.quoteInfo) { r = open_read_and_close (ctx.quoteInfo, (void**)"eInfo, NULL); if (r) { free (qualifyingData); free (signature); return -1; } } char *pcrLog = NULL; if (ctx.pcrLog) { r = open_read_and_close (ctx.pcrLog, (void**)&pcrLog, NULL); if (r) { free (qualifyingData); free (signature); free (quoteInfo); return -1; } } /* Execute FAPI command with passed arguments */ r = Fapi_VerifyQuote (fctx, ctx.publicKeyPath, qualifyingData, qualifyingDataSize, quoteInfo, signature, signatureSize, pcrLog); if (r != TSS2_RC_SUCCESS){ free (qualifyingData); free (signature); free (quoteInfo); free (pcrLog); LOG_PERR ("Fapi_VerifyQuote", r); return 1; } free (qualifyingData); free (signature); free (quoteInfo); free (pcrLog); return 0; } TSS2_TOOL_REGISTER("verifyquote", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_verifysignature.c000066400000000000000000000054121412464516500220360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed commandline parameters */ static struct cxt { char const *digest; char const *publicKeyPath; char const *signature; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'd': ctx.digest = value; break; case 'p': ctx.publicKeyPath = value; break; case 'i': ctx.signature = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"keyPath", required_argument, NULL, 'p'}, {"digest", required_argument, NULL, 'd'}, {"signature", required_argument, NULL, 'i'} }; return (*opts = tpm2_options_new ("d:p:i:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.publicKeyPath) { fprintf (stderr, "public key path parameter not provided, use " \ "--keyPath\n"); return -1; } if (!ctx.digest) { fprintf (stderr, "digest parameter not provided, use --digest\n"); return -1; } if (!ctx.signature) { fprintf (stderr, "signature parameter not provided, use "\ "--signature\n"); return -1; } /* Check exclusive access to stdin */ int count_in = 0; if (ctx.digest && !strcmp (ctx.digest, "-")) count_in +=1; if (ctx.signature && !strcmp (ctx.signature, "-")) count_in +=1; if (count_in > 1) { fprintf (stderr, "Only one of --digest and --signature can read from -"\ "(standard input)\n"); return -1; } /* Read data needed for signature verification */ uint8_t *digest, *signature; size_t digestSize, signatureSize; TSS2_RC r = open_read_and_close (ctx.digest, (void**)&digest, &digestSize); if (r){ return 1; } r = open_read_and_close (ctx.signature, (void**)&signature, &signatureSize); if (r) { free (digest); return 1; } /* Execute FAPI command with passed arguments */ r = Fapi_VerifySignature (fctx, ctx.publicKeyPath, digest, digestSize, signature, signatureSize); if (r != TSS2_RC_SUCCESS){ free (digest); free (signature); LOG_PERR("Fapi_Key_VerifySignature", r); return 1; } free (digest); free (signature); return 0; } TSS2_TOOL_REGISTER("verifysignature", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/fapi/tss2_writeauthorizenv.c000066400000000000000000000031221412464516500222350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tools/fapi/tss2_template.h" /* Context struct used to store passed command line parameters */ static struct cxt { char const *nvPath; char const *policyPath; } ctx; /* Parse command line parameters */ static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.nvPath = value; break; case 'P': ctx.policyPath = value; break; } return true; } /* Define possible command line parameters */ static bool tss2_tool_onstart(tpm2_options **opts) { struct option topts[] = { {"nvPath" , required_argument, NULL, 'p'}, {"policyPath" , required_argument, NULL, 'P'} }; return (*opts = tpm2_options_new ("p:P:", ARRAY_LEN(topts), topts, on_option, NULL, 0)) != NULL; } /* Execute specific tool */ static int tss2_tool_onrun (FAPI_CONTEXT *fctx) { /* Check availability of required parameters */ if (!ctx.nvPath) { fprintf (stderr, "No NV path provided, use --nvPath\n"); return -1; } if (!ctx.policyPath) { fprintf (stderr, "No policy path provided, use --policyPath\n"); return -1; } /* Execute FAPI command with passed arguments */ TSS2_RC r = Fapi_WriteAuthorizeNv(fctx, ctx.nvPath, ctx.policyPath); if (r != TSS2_RC_SUCCESS){ LOG_PERR ("Fapi_WriteAuthorizeNv", r); return 1; } return 0; } TSS2_TOOL_REGISTER("writeauthorizenv", tss2_tool_onstart, tss2_tool_onrun, NULL) tpm2-tools-5.2/tools/misc/000077500000000000000000000000001412464516500155035ustar00rootroot00000000000000tpm2-tools-5.2/tools/misc/tpm2_certifyX509certutil.c000066400000000000000000000162711412464516500224270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include "log.h" #include "tpm2_tool.h" typedef struct { ASN1_TIME *notBefore; ASN1_TIME *notAfter; } TPM2_PARTIAL_CERT_VALIDITY; typedef struct { X509_ALGOR *algorithm; X509_NAME *issuer; TPM2_PARTIAL_CERT_VALIDITY *validity; X509_NAME *subject; STACK_OF(X509_EXTENSION) *extensions; } TPM2_PARTIAL_CERT; ASN1_SEQUENCE(TPM2_PARTIAL_CERT_VALIDITY) = { ASN1_SIMPLE(TPM2_PARTIAL_CERT_VALIDITY, notBefore, ASN1_TIME), ASN1_SIMPLE(TPM2_PARTIAL_CERT_VALIDITY, notAfter, ASN1_TIME), } ASN1_SEQUENCE_END(TPM2_PARTIAL_CERT_VALIDITY) /* partialCertificate per Part 3, 18.8.1 */ ASN1_SEQUENCE(TPM2_PARTIAL_CERT) = { ASN1_OPT(TPM2_PARTIAL_CERT, algorithm, X509_ALGOR), ASN1_SIMPLE(TPM2_PARTIAL_CERT, issuer, X509_NAME), ASN1_SIMPLE(TPM2_PARTIAL_CERT, validity, TPM2_PARTIAL_CERT_VALIDITY), ASN1_SIMPLE(TPM2_PARTIAL_CERT, subject, X509_NAME), ASN1_EXP_SEQUENCE_OF(TPM2_PARTIAL_CERT, extensions, X509_EXTENSION, 3), } ASN1_SEQUENCE_END(TPM2_PARTIAL_CERT) IMPLEMENT_ASN1_FUNCTIONS(TPM2_PARTIAL_CERT) int i2d_TPM2_PARTIAL_CERT_bio(BIO *bp, const TPM2_PARTIAL_CERT *a) { return ASN1_i2d_bio_of(TPM2_PARTIAL_CERT, i2d_TPM2_PARTIAL_CERT, bp, a); } int TPM2_add_ext(TPM2_PARTIAL_CERT *x, X509_EXTENSION *ex, int loc) { return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); } struct tpm_gen_partial_cert { const char *out_path; const char *valid_str; const char *subject; const char *issuer; }; #define CERT_FILE "partial_cert.der" #define VALID_DAYS "3560" #define SUBJ "C=US;O=CA org;OU=CA unit;CN=example" #define ISSUER "C=US;O=CA org;OU=CA unit;CN=example" static struct tpm_gen_partial_cert ctx = { .out_path = CERT_FILE, .valid_str = VALID_DAYS, .subject = SUBJ, .issuer = ISSUER }; static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.out_path = value; break; case 'd': ctx.valid_str = value; break; case 's': ctx.subject = value; break; case 'i': ctx.issuer = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "outcert", optional_argument, NULL, 'o' }, { "days", optional_argument, NULL, 'd' }, { "subject", optional_argument, NULL, 's' }, { "issuer", optional_argument, NULL, 'i' } }; *opts = tpm2_options_new("o:d:s:i:", ARRAY_LEN(topts), topts, on_option, NULL, TPM2_OPTIONS_NO_SAPI); return *opts != NULL; } struct name_fields { const char *field; const char *del; const char *def; int maxlen; }; static struct name_fields names[] = { { .field = "CN", .del = "CN=", .maxlen = 8, .def = "default" }, { .field = "C", .del = "C=", .maxlen = 2, .def = "US" }, { .field = "O", .del = "O=", .maxlen = 8, .def = "CA Org" }, { .field = "OU", .del = "OU=", .maxlen = 8, .def = "CA Unit" }, }; static int populate_fields(X509_NAME *name, const char *opt) { char *name_opt = strdup(opt); if (!name_opt) { LOG_ERR("Alloc failed"); return -1; } const char *tok = strtok(name_opt, ";"); unsigned i = 0; int fields_added = 0; while (tok != NULL) { LOG_INFO("Parsing token %s", tok); /* Loop through supported fields and add them if found */ for (i = 0; i < ARRAY_LEN(names); i++) { const char *del = names[i].del; const char *fld = names[i].field; unsigned int maxlen = names[i].maxlen; size_t len = strlen(del); const char *ptr; if (strncmp(tok, del, len) == 0) { if (strlen(tok + len) > maxlen || strlen(tok + len) == 0) { LOG_WARN("Field %s too long or empty. Using default", fld); ptr = names[i].def; } else { ptr = tok + len; } LOG_INFO("Adding name field %s%s", del, ptr); int ret = X509_NAME_add_entry_by_txt(name, fld, MBSTRING_ASC, (const unsigned char *) ptr, -1, -1, 0); if (ret != 1) { free(name_opt); LOG_ERR("X509_NAME_add_entry_by_txt"); return -1; } fields_added++; } } tok = strtok(NULL, ";"); } free(name_opt); return fields_added; } static tool_rc generate_partial_X509() { BIO *cert_out = BIO_new_file(ctx.out_path, "wb"); if (!cert_out) { LOG_ERR("Can not create file %s", ctx.out_path); return -1; } X509_EXTENSION *extv3 = NULL; TPM2_PARTIAL_CERT *cert = TPM2_PARTIAL_CERT_new(); if (!cert) { LOG_ERR("TPM2_PARTIAL_CERT_new"); goto out_err; } /* populate issuer */ int fields_added = populate_fields(cert->issuer, ctx.issuer); if (fields_added <= 0) { LOG_ERR("Could not parse any issuer fields"); goto out_err; } else { LOG_INFO("Added %d issuer fields", fields_added); } /* populate validity */ unsigned int valid_days; if (!tpm2_util_string_to_uint32(ctx.valid_str, &valid_days)) { LOG_ERR("string_to_uint32"); goto out_err; } X509_gmtime_adj(cert->validity->notBefore, 0); // add valid not before X509_gmtime_adj(cert->validity->notAfter, valid_days * 86400); // add valid not after /* populate subject */ fields_added = populate_fields(cert->subject, ctx.subject); if (fields_added <= 0) { LOG_ERR("Could not parse any subject fields"); goto out_err; } else { LOG_INFO("Added %d subject fields", fields_added); } /* populate extensions */ extv3 = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "critical,digitalSignature,keyCertSign,cRLSign"); if (!extv3) { LOG_ERR("X509V3_EXT_conf_nid"); goto out_err; } int ret = TPM2_add_ext(cert, extv3, -1); // add required v3 extention: key usage if (ret != 1) { LOG_ERR("X509_add_ext"); goto out_err; } /* output */ ret = i2d_TPM2_PARTIAL_CERT_bio(cert_out, cert); // print cert in DER format if (ret != 1) { LOG_ERR("i2d_X509_bio"); goto out_err; } X509_EXTENSION_free(extv3); TPM2_PARTIAL_CERT_free(cert); BIO_free_all(cert_out); return tool_rc_success; out_err: BIO_free_all(cert_out); X509_EXTENSION_free(extv3); TPM2_PARTIAL_CERT_free(cert); return tool_rc_general_error; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); UNUSED(ectx); return generate_partial_X509(); } TPM2_TOOL_REGISTER("certifyX509certutil", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/misc/tpm2_checkquote.c000066400000000000000000000465541412464516500207620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_options.h" #include "tpm2_systemdeps.h" #include "tpm2_tool.h" #include "tpm2_eventlog.h" typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx; struct tpm2_verifysig_ctx { union { struct { UINT8 msg :1; UINT8 sig :1; UINT8 pcr :1; UINT8 hlg :1; UINT8 eventlog :1; }; UINT8 all; } flags; TPMI_ALG_HASH halg; TPM2B_DIGEST msg_hash; TPM2B_DIGEST pcr_hash; TPMS_ATTEST attest; TPM2B_DATA extra_data; TPM2B_MAX_BUFFER signature; char *msg_file_path; char *sig_file_path; char *out_file_path; char *pcr_file_path; const char *pubkey_file_path; char *eventlog_path; tpm2_loaded_object key_context_object; const char *pcr_selection_string; }; static tpm2_verifysig_ctx ctx = { .halg = TPM2_ALG_SHA256, .msg_hash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer), .pcr_hash = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer), }; static bool verify(void) { bool result = false; /* read the public key */ EVP_PKEY *pkey = NULL; bool ret = tpm2_public_load_pkey(ctx.pubkey_file_path, &pkey); if (!ret) { return false; } EVP_PKEY_CTX *pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); if (!pkey_ctx) { LOG_ERR("EVP_PKEY_CTX_new failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto err; } /* get the digest alg */ /* TODO SPlit loading on plain vs tss format to detect the hash alg */ /* If its a plain sig we need -g */ const EVP_MD *md = tpm2_openssl_md_from_tpmhalg(ctx.halg); // TODO error handling int rc = EVP_PKEY_verify_init(pkey_ctx); if (!rc) { LOG_ERR("EVP_PKEY_verify_init failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto err; } rc = EVP_PKEY_CTX_set_signature_md(pkey_ctx, md); if (!rc) { LOG_ERR("EVP_PKEY_CTX_set_signature_md failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto err; } /* TODO dump actual signature */ tpm2_tool_output("sig: "); tpm2_util_hexdump(ctx.signature.buffer, ctx.signature.size); tpm2_tool_output("\n"); // Verify the signature matches message digest rc = EVP_PKEY_verify(pkey_ctx, ctx.signature.buffer, ctx.signature.size, ctx.msg_hash.buffer, ctx.msg_hash.size); if (rc != 1) { if (rc == 0) { LOG_ERR("Error validating signed message with public key provided"); } else { LOG_ERR("Error %s", ERR_error_string(ERR_get_error(), NULL)); } goto err; } // Ensure nonce is the same as given if (ctx.attest.extraData.size != ctx.extra_data.size || memcmp(ctx.attest.extraData.buffer, ctx.extra_data.buffer, ctx.extra_data.size) != 0) { LOG_ERR("Error validating nonce from quote"); goto err; } // Also ensure digest from quote matches PCR digest if (ctx.flags.pcr) { if (!tpm2_util_verify_digests(&ctx.attest.attested.quote.pcrDigest, &ctx.pcr_hash)) { LOG_ERR("Error validating PCR composite against signed message"); goto err; } } result = true; err: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(pkey_ctx); return result; } static TPM2B_ATTEST *message_from_file(const char *msg_file_path) { unsigned long size; bool result = files_get_file_size_path(msg_file_path, &size); if (!result) { return NULL; } if (!size) { LOG_ERR("The msg file \"%s\" is empty", msg_file_path); return NULL; } TPM2B_ATTEST *msg = (TPM2B_ATTEST *) calloc(1, sizeof(TPM2B_ATTEST) + size); if (!msg) { LOG_ERR("OOM"); return NULL; } UINT16 tmp = msg->size = size; if (!files_load_bytes_from_path(msg_file_path, msg->attestationData, &tmp)) { free(msg); return NULL; } return msg; } static bool parse_selection_data_from_selection_string(FILE *pcr_input, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { bool result = pcr_parse_selections(ctx.pcr_selection_string, pcr_select); if (!result) { LOG_ERR("Could not parse PCR selections"); return false; } /* * A tpm2_pcrs->pcr_values[tpm2_pcrs->count] is a TPML_DIGEST structure * which can hold a maximum of 8 digests. Once the count of 8 is exhausted * we need a new TPML_DIGEST structure. * * The digests count in a list is tracked with * tpm2_pcrs->pcr_values[tpm2_pcrs->count].count * * A total of such lists is tracked by the tpm2_pcrs->count. */ unsigned i = 0; unsigned j = 0; unsigned read_size = 0; size_t read_count = 0; unsigned digest_list_count = 0; memset(pcrs, 0, sizeof(tpm2_pcrs)); /* * Iterate through all the PCR banks selected. */ for (i = 0; i < pcr_select->count; i++) { /* * Ensure all the digests across banks can fit in tpm2_pcrs. */ if (digest_list_count >= TPM2_MAX_PCRS - 1) { LOG_ERR("Maximum count for allowed digest lists reached."); return false; } /* * Digest size of PCR bank selected in this iteration. */ read_size = tpm2_alg_util_get_hash_size(pcr_select->pcrSelections[i].hash); /* * Iterate through pcrSelect bytes to find selected PCR index bitmap. */ for (j = 0; j < pcr_select->pcrSelections[i].sizeofSelect * 8; j++) { /* * Test if PCR index select is true. */ if ((pcr_select->pcrSelections[i].pcrSelect[j / 8] & 1 << (j % 8)) != 0) { /* * Read the digest at a selected PCR index. */ pcrs->pcr_values[digest_list_count].digests[pcrs->pcr_values[ digest_list_count].count].size = read_size; read_count = fread(pcrs->pcr_values[digest_list_count].digests[ pcrs->pcr_values[digest_list_count].count].buffer, read_size, 1, pcr_input); if (read_count != 1) { LOG_ERR("Failed to read PCR digests from file"); return false; } /* * Ensure we don't overrun the allowed digest count in a * TPML_DIGEST. */ if (pcrs->pcr_values[digest_list_count].count == 7) { digest_list_count++; } else { /* * Ensure we populate the digest in a new list if we * exhausted the digest count in the current TPML_DIGEST * instance. */ pcrs->pcr_values[digest_list_count].count++; } } } } /* * Update the count of total TPML_DIGEST consumed to accomodate all the * selected PCR indices across all the banks. */ pcrs->count = digest_list_count + 1; return true; } static bool parse_selection_data_from_file(FILE *pcr_input, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { // Import TPML_PCR_SELECTION structure to pcr outfile if (fread(pcr_select, sizeof(TPML_PCR_SELECTION), 1, pcr_input) != 1) { LOG_ERR("Failed to read PCR selection from file"); return false; } // Import PCR digests to pcr outfile if (fread(&pcrs->count, sizeof(UINT32), 1, pcr_input) != 1) { LOG_ERR("Failed to read PCR digests header from file"); return false; } if (le64toh(pcrs->count) > ARRAY_LEN(pcrs->pcr_values)) { LOG_ERR("Malformed PCR file, pcr count cannot be greater than %zu, got: %" PRIu64 " ", ARRAY_LEN(pcrs->pcr_values), le64toh((UINT64)pcrs->count)); return false; } size_t j; for (j = 0; j < le64toh(pcrs->count); j++) { if (fread(&pcrs->pcr_values[j], sizeof(TPML_DIGEST), 1, pcr_input) != 1) { LOG_ERR("Failed to read PCR digest from file"); return false; } } return true; } static bool pcrs_from_file(const char *pcr_file_path, TPML_PCR_SELECTION *pcr_select, tpm2_pcrs *pcrs) { bool result = false; unsigned long size; if (!files_get_file_size_path(pcr_file_path, &size)) { return false; } if (!size) { LOG_ERR("The pcr file \"%s\" is empty", pcr_file_path); return false; } FILE *pcr_input = fopen(pcr_file_path, "rb"); if (!pcr_input) { LOG_ERR("Could not open PCRs input file \"%s\" error: \"%s\"", pcr_file_path, strerror(errno)); goto out; } if (!ctx.pcr_selection_string) { result = parse_selection_data_from_file(pcr_input, pcr_select, pcrs); if (!result) { goto out; } } else { result = parse_selection_data_from_selection_string(pcr_input, pcr_select, pcrs); if (!result) { goto out; } } result = true; out: if (pcr_input) { fclose(pcr_input); } return result; } static bool eventlog_from_file(tpm2_eventlog_context *evctx, const char *file_path) { unsigned long size; if (!files_get_file_size_path(file_path, &size)) { return false; } if (!size) { LOG_ERR("The eventlog file \"%s\" is empty", file_path); return false; } uint8_t *eventlog = calloc(1, size); if (!eventlog) { LOG_ERR("OOM"); return false; } uint16_t size_tmp = size; if (!files_load_bytes_from_path(file_path, eventlog, &size_tmp)) { free(eventlog); return false; } bool rc = parse_eventlog(evctx, eventlog, size); free(eventlog); return rc; } static tool_rc init(void) { /* check flags for mismatches */ if (!(ctx.pubkey_file_path && ctx.flags.sig && ctx.flags.msg)) { LOG_ERR( "--pubkey (-u), --msg (-m) and --sig (-s) are required"); return tool_rc_option_error; } if (ctx.flags.eventlog && !ctx.flags.pcr) { LOG_ERR("PCR file is required to validate eventlog"); return tool_rc_option_error; } TPM2B_ATTEST *msg = NULL; TPML_PCR_SELECTION pcr_select; tpm2_pcrs *pcrs; tpm2_pcrs temp_pcrs = {}; tool_rc return_value = tool_rc_general_error; msg = message_from_file(ctx.msg_file_path); if (!msg) { /* message_from_file() logs specific error no need to here */ return tool_rc_general_error; } /* * If the caller specifies the signature format, like rsassa, that means * the caller doesn't have the TPMT signature, but rather a plain signature, * and we need to trust what was set in -g as the hash algorithm. The * verification will fail. * * In the case of the TSS signature format, we have the hash alg, so if the user * specifies the hash alg, or we're guessing, we should use the right one. */ TPMI_ALG_HASH expected_halg = TPM2_ALG_ERROR; bool res = tpm2_convert_sig_load_plain(ctx.sig_file_path, &ctx.signature, &expected_halg); if (!res) { goto err; } if (expected_halg != TPM2_ALG_NULL) { if (ctx.halg != expected_halg) { if (ctx.flags.hlg) { const char *got_str = tpm2_alg_util_algtostr(ctx.halg, tpm2_alg_util_flags_any); const char *expected_str = tpm2_alg_util_algtostr(expected_halg, tpm2_alg_util_flags_any); LOG_WARN("User specified hash algorithm of \"%s\", does not match" "expected hash algorithm of \"%s\", using: \"%s\"", got_str, expected_str, expected_str); } ctx.halg = expected_halg; } } /* If no digest is specified, compute it */ if (!ctx.flags.msg) { /* * This is a redundant check since main() checks this case, but we'll add it here to silence any * complainers. */ LOG_ERR("No digest set and no message file to compute from, cannot " "compute message hash!"); goto err; } if (ctx.flags.pcr) { if (pcrs_from_file(ctx.pcr_file_path, &pcr_select, &temp_pcrs)) { /* pcrs_from_file() logs specific error no need to here */ pcrs = &temp_pcrs; } else { goto err; } if (le32toh(pcr_select.count) > TPM2_NUM_PCR_BANKS) goto err; UINT32 i; for (i = 0; i < le32toh(pcr_select.count); i++) if (le16toh(pcr_select.pcrSelections[i].hash) == TPM2_ALG_ERROR) goto err; if (!tpm2_openssl_hash_pcr_banks_le(ctx.halg, &pcr_select, pcrs, &ctx.pcr_hash)) { LOG_ERR("Failed to hash PCR values related to quote!"); goto err; } if (!pcr_print_pcr_struct_le(&pcr_select, pcrs)) { LOG_ERR("Failed to print PCR values related to quote!"); goto err; } } if (ctx.flags.eventlog && ctx.flags.pcr) { if (pcrs_from_file(ctx.pcr_file_path, &pcr_select, &temp_pcrs)) { /* pcrs_from_file() logs specific error no need to here */ pcrs = &temp_pcrs; } else { goto err; } if (pcr_select.count > TPM2_NUM_PCR_BANKS) goto err; tpm2_eventlog_context eventlog_ctx = { 0 }; bool rc = eventlog_from_file(&eventlog_ctx, ctx.eventlog_path); if (!rc) { LOG_ERR("Failed to process eventlog"); goto err; } bool eventlog_fail = false; unsigned vi = 0; unsigned di = 0; for (unsigned i = 0; i < pcr_select.count; i++) { const TPMS_PCR_SELECTION *const sel = &pcr_select.pcrSelections[i]; // Loop through all PCRs in this bank const unsigned bank_size = sel->sizeofSelect * 8; for (unsigned pcr_id = 0; pcr_id < bank_size; pcr_id++) { // skip non-selected banks if (!tpm2_util_is_pcr_select_bit_set(sel, pcr_id)) { continue; } if (vi >= pcrs->count || di >= pcrs->pcr_values[vi].count) { LOG_ERR("Something wrong, trying to print but nothing more"); eventlog_fail = true; break; } // Compare this digest to the computed value from the eventlog const TPM2B_DIGEST *pcr = &pcrs->pcr_values[vi].digests[di]; const uint8_t *pcr_q = pcr->buffer; const uint8_t *pcr_e = NULL; if (sel->hash == TPM2_ALG_SHA1 && pcr->size == TPM2_SHA1_DIGEST_SIZE) { pcr_e = eventlog_ctx.sha1_pcrs[pcr_id]; } else if (sel->hash == TPM2_ALG_SHA256 && pcr->size == TPM2_SHA256_DIGEST_SIZE) { pcr_e = eventlog_ctx.sha256_pcrs[pcr_id]; } else if (sel->hash == TPM2_ALG_SHA384 && pcr->size == TPM2_SHA384_DIGEST_SIZE) { pcr_e = eventlog_ctx.sha384_pcrs[pcr_id]; } else if (sel->hash == TPM2_ALG_SHA512 && pcr->size == TPM2_SHA512_DIGEST_SIZE) { pcr_e = eventlog_ctx.sha512_pcrs[pcr_id]; } else if (sel->hash == TPM2_ALG_SM3_256 && pcr->size == TPM2_SM3_256_DIGEST_SIZE) { pcr_e = eventlog_ctx.sm3_256_pcrs[pcr_id]; } else { LOG_WARN("PCR%u unsupported algorithm/size %u/%u", pcr_id, sel->hash, pcr->size); eventlog_fail = 1; } if (pcr_e && memcmp(pcr_e, pcr_q, pcr->size) != 0) { LOG_WARN("PCR%u mismatch", pcr_id); eventlog_fail = 1; } if (++di < pcrs->pcr_values[vi].count) { continue; } di = 0; if (++vi < pcrs->count) { continue; } } } if (eventlog_fail) { LOG_ERR("Eventlog and quote PCR mismatch"); goto err; } } tool_rc tmp_rc = files_tpm2b_attest_to_tpms_attest(msg, &ctx.attest); if (tmp_rc != tool_rc_success) { return_value = tmp_rc; goto err; } // Figure out the digest for this message res = tpm2_openssl_hash_compute_data(ctx.halg, msg->attestationData, msg->size, &ctx.msg_hash); if (!res) { LOG_ERR("Compute message hash failed!"); goto err; } return_value = tool_rc_success; err: free(msg); return return_value; } static bool on_option(char key, char *value) { switch (key) { case 'u': ctx.pubkey_file_path = value; break; case 'g': { ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Unable to convert algorithm, got: \"%s\"", value); return false; } ctx.flags.hlg = 1; } break; case 'm': { ctx.msg_file_path = value; ctx.flags.msg = 1; } break; case 'F': LOG_WARN("DEPRECATED: Format ignored"); break; case 'q': ctx.extra_data.size = sizeof(ctx.extra_data.buffer); return tpm2_util_bin_from_hex_or_file(value, &ctx.extra_data.size, ctx.extra_data.buffer); break; case 's': ctx.sig_file_path = value; ctx.flags.sig = 1; break; case 'f': ctx.pcr_file_path = value; ctx.flags.pcr = 1; break; case 'e': ctx.eventlog_path = value; ctx.flags.eventlog = 1; break; case 'l': ctx.pcr_selection_string = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hash-algorithm", required_argument, NULL, 'g' }, { "message", required_argument, NULL, 'm' }, { "format", required_argument, NULL, 'F' }, { "signature", required_argument, NULL, 's' }, { "eventlog", required_argument, NULL, 'e' }, { "pcr", required_argument, NULL, 'f' }, { "pcr-list", required_argument, NULL, 'l' }, { "public", required_argument, NULL, 'u' }, { "qualification", required_argument, NULL, 'q' }, }; *opts = tpm2_options_new("g:m:F:s:u:f:q:e:l:", ARRAY_LEN(topts), topts, on_option, NULL, TPM2_OPTIONS_NO_SAPI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(ectx); UNUSED(flags); /* initialize and process */ tool_rc rc = init(); if (rc != tool_rc_success) { return rc; } bool res = verify(); if (!res) { LOG_ERR("Verify signature failed!"); return tool_rc_general_error; } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("checkquote", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/misc/tpm2_eventlog.c000066400000000000000000000062741412464516500204450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "files.h" #include "log.h" #include "efi_event.h" #include "tpm2_eventlog.h" #include "tpm2_eventlog_yaml.h" #include "tpm2_tool.h" #define CHUNK_SIZE 16384 static char *filename = NULL; /* Set the default YAML version */ static uint32_t eventlog_version = 1; static bool on_positional(int argc, char **argv) { if (argc != 1) { LOG_ERR("Expected one file name as a positional parameter. Got: %d", argc); return false; } filename = argv[0]; return true; } static bool on_option(char key, char *value) { uint32_t version; switch (key) { case 0: if (!tpm2_util_string_to_uint32(value, &version)) { LOG_ERR("Cannot parse eventlog version: %s\n", value); return false; } if (version < MIN_EVLOG_YAML_VERSION || version > MAX_EVLOG_YAML_VERSION) { LOG_ERR("Unexpected YAML version number: %u\n", version); return false; } eventlog_version = version; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "eventlog-version", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("y:", ARRAY_LEN(topts), topts, on_option, on_positional, TPM2_OPTIONS_NO_SAPI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); UNUSED(ectx); if (filename == NULL) { LOG_ERR("Missing required positional parameter, try -h / --help"); return tool_rc_option_error; } /* Read the file in chunks. Usually the file will reside in securityfs, and those files do not have a public file size */ FILE *fileptr = fopen(filename, "rb"); if (!fileptr) { return tool_rc_general_error; } /* Reserve the buffer for the first chunk */ tool_rc rc = tool_rc_success; UINT8 *eventlog = calloc(1, CHUNK_SIZE); if (eventlog == NULL){ LOG_ERR("failed to allocate %d bytes: %s", CHUNK_SIZE, strerror(errno)); rc = tool_rc_general_error; goto out; } size_t size = 0; bool is_file_read = false; do { is_file_read = files_read_bytes_chunk(fileptr, eventlog + size, CHUNK_SIZE, &size); UINT8 *eventlog_tmp = realloc(eventlog, size + CHUNK_SIZE); if (!eventlog_tmp){ LOG_ERR("failed to allocate %zu bytes: %s", size + CHUNK_SIZE, strerror(errno)); rc = tool_rc_general_error; goto out; } eventlog = eventlog_tmp; } while (is_file_read); /* Parse eventlog data */ bool ret = yaml_eventlog(eventlog, size, eventlog_version); if (!ret) { LOG_ERR("failed to parse tpm2 eventlog"); rc = tool_rc_general_error; } out: if (fileptr) { fclose(fileptr); } if (eventlog) { free(eventlog); } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("eventlog", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/misc/tpm2_print.c000066400000000000000000000262301412464516500177500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_tool.h" #include "tpm2_util.h" typedef bool (*print_fn)(FILE *f); #define FLAG_FMT (1 << 0) typedef struct tpm2_print_ctx tpm2_print_ctx; struct tpm2_print_ctx { struct { const char *path; print_fn handler; } file; bool format_set; tpm2_convert_pubkey_fmt format; }; static tpm2_print_ctx ctx = { .format = pubkey_format_tss }; static void print_clock_info(TPMS_CLOCK_INFO *clock_info, size_t indent_count) { print_yaml_indent(indent_count); tpm2_tool_output("clock: %"PRIu64"\n", clock_info->clock); print_yaml_indent(indent_count); tpm2_tool_output("resetCount: %"PRIu32"\n", clock_info->resetCount); print_yaml_indent(indent_count); tpm2_tool_output("restartCount: %"PRIu32"\n", clock_info->restartCount); print_yaml_indent(indent_count); tpm2_tool_output("safe: %u\n", clock_info->safe); } static bool print_TPMS_QUOTE_INFO(TPMS_QUOTE_INFO *info, size_t indent_count) { print_yaml_indent(indent_count); tpm2_tool_output("pcrSelect:\n"); print_yaml_indent(indent_count + 1); tpm2_tool_output("count: %"PRIu32"\n", info->pcrSelect.count); print_yaml_indent(indent_count + 1); tpm2_tool_output("pcrSelections:\n"); // read TPML_PCR_SELECTION array (of size count) UINT32 i; for (i = 0; i < info->pcrSelect.count; ++i) { print_yaml_indent(indent_count + 2); tpm2_tool_output("%"PRIu32":\n", i); // print hash type (TPMI_ALG_HASH) const char* const hash_name = tpm2_alg_util_algtostr( info->pcrSelect.pcrSelections[i].hash, tpm2_alg_util_flags_hash); if (!hash_name) { LOG_ERR("Invalid hash type in quote"); return false; } print_yaml_indent(indent_count + 3); tpm2_tool_output("hash: %"PRIu16" (%s)\n", info->pcrSelect.pcrSelections[i].hash, hash_name); print_yaml_indent(indent_count + 3); tpm2_tool_output("sizeofSelect: %"PRIu8"\n", info->pcrSelect.pcrSelections[i].sizeofSelect); // print PCR selection in hex print_yaml_indent(indent_count + 3); tpm2_tool_output("pcrSelect: "); tpm2_util_hexdump((BYTE *)&info->pcrSelect.pcrSelections[i].pcrSelect, info->pcrSelect.pcrSelections[i].sizeofSelect); tpm2_tool_output("\n"); } // print digest in hex (a TPM2B object) print_yaml_indent(indent_count); tpm2_tool_output("pcrDigest: "); tpm2_util_print_tpm2b(&info->pcrDigest); tpm2_tool_output("\n"); return true; } static bool print_TPMS_ATTEST(FILE* fd) { TPMS_ATTEST attest = { 0 }; bool res = files_load_attest_file(fd, ctx.file.path, &attest); if (!res) { LOG_ERR("Could not parse TPMS_ATTEST file: \"%s\"", ctx.file.path); return false; } tpm2_tool_output("magic: "); /* dump these in TPM endianess (big-endian) */ typeof(attest.magic) be_magic = tpm2_util_hton_32(attest.magic); tpm2_util_hexdump((const UINT8*) &be_magic, sizeof(attest.magic)); tpm2_tool_output("\n"); // check magic if (attest.magic != TPM2_GENERATED_VALUE) { LOG_ERR("Bad magic, got: 0x%x, expected: 0x%x", attest.magic, TPM2_GENERATED_VALUE); return false; } tpm2_tool_output("type: "); /* dump these in TPM endianess (big-endian) */ typeof(attest.type) be_type = tpm2_util_hton_16(attest.type); tpm2_util_hexdump((const UINT8*) &be_type, sizeof(attest.type)); tpm2_tool_output("\n"); tpm2_tool_output("qualifiedSigner: "); tpm2_util_print_tpm2b(&attest.qualifiedSigner); tpm2_tool_output("\n"); tpm2_tool_output("extraData: "); tpm2_util_print_tpm2b(&attest.extraData); tpm2_tool_output("\n"); tpm2_tool_output("clockInfo:\n"); print_clock_info(&attest.clockInfo, 1); tpm2_tool_output("firmwareVersion: "); tpm2_util_hexdump((BYTE *)&attest.firmwareVersion, sizeof(attest.firmwareVersion)); tpm2_tool_output("\n"); switch (attest.type) { case TPM2_ST_ATTEST_QUOTE: tpm2_tool_output("attested:\n"); print_yaml_indent(1); tpm2_tool_output("quote:\n"); return print_TPMS_QUOTE_INFO(&attest.attested.quote, 2); break; default: LOG_ERR("Cannot print unsupported type 0x%" PRIx16, attest.type); return false; } /* Should be unreachable */ return false; } static bool print_TPMS_CONTEXT(FILE *fstream) { /* * Reading the TPMS_CONTEXT structure to disk, format: * TPM2.0-TOOLS HEADER * U32 hierarchy * U32 savedHandle * U64 sequence * U16 contextBlobLength * BYTE[] contextBlob */ UINT32 version; TPMS_CONTEXT context; bool result = files_read_header(fstream, &version); if (!result) { LOG_WARN("The loaded tpm context does not appear to be in the proper " "format, assuming old format."); rewind(fstream); result = files_read_bytes(fstream, (UINT8 *) &context, sizeof(context)); if (!result) { LOG_ERR("Could not load tpm context file"); goto out; } else { goto print_context; } } result = files_read_32(fstream, &context.hierarchy); if (!result) { LOG_ERR("Error reading hierarchy!"); goto out; } result = files_read_32(fstream, &context.savedHandle); if (!result) { LOG_ERR("Error reading savedHandle!"); goto out; } result = files_read_64(fstream, &context.sequence); if (!result) { LOG_ERR("Error reading sequence!"); goto out; } result = files_read_16(fstream, &context.contextBlob.size); if (!result) { LOG_ERR("Error reading contextBlob.size!"); goto out; } if (context.contextBlob.size > sizeof(context.contextBlob.buffer)) { LOG_ERR("Size mismatch found on contextBlob, got %"PRIu16" expected " "less than or equal to %zu", context.contextBlob.size, sizeof(context.contextBlob.buffer)); result = false; goto out; } result = files_read_bytes(fstream, context.contextBlob.buffer, context.contextBlob.size); if (!result) { LOG_ERR("Error reading contextBlob.size!"); goto out; } print_context: tpm2_tool_output("version: %d\n", version); const char *hierarchy; switch (context.hierarchy) { case TPM2_RH_OWNER: hierarchy = "owner"; break; case TPM2_RH_PLATFORM: hierarchy = "platform"; break; case TPM2_RH_ENDORSEMENT: hierarchy = "endorsement"; break; case TPM2_RH_NULL: default: hierarchy = "null"; break; } tpm2_tool_output("hierarchy: %s\n", hierarchy); tpm2_tool_output("handle: 0x%X (%u)\n", context.savedHandle, context.savedHandle); tpm2_tool_output("sequence: %"PRIu64"\n", context.sequence); tpm2_tool_output("contextBlob: \n"); tpm2_tool_output("\tsize: %d\n", context.contextBlob.size); result = true; out: return result; } static bool print_TPMT_PUBLIC(FILE *fstream) { TPMT_PUBLIC public = { 0 }; bool res = files_load_template_file(fstream, ctx.file.path, &public); if (!res) { return res; } if (ctx.format_set) { TPM2B_PUBLIC tpm2b_public = { .publicArea = public }; return tpm2_convert_pubkey_save(&tpm2b_public, ctx.format, NULL); } tpm2_util_tpmt_public_to_yaml(&public, NULL); return true; } static bool print_TPM2B_PUBLIC(FILE *fstream) { TPM2B_PUBLIC public = { 0 }; bool res = files_load_public_file(fstream, ctx.file.path, &public); if (!res) { return res; } if (ctx.format_set) { return tpm2_convert_pubkey_save(&public, ctx.format, NULL); } tpm2_util_public_to_yaml(&public, NULL); return true; } #define ADD_HANDLER(type) { .name = #type, .flags = 0, .fn = print_##type } #define ADD_HANDLER_FMT(type) { .name = #type, .flags = FLAG_FMT, .fn = print_##type } static bool handle_type(const char *name) { static const struct { const char *name; unsigned flags; print_fn fn; } handlers[] = { ADD_HANDLER(TPMS_ATTEST), ADD_HANDLER(TPMS_CONTEXT), ADD_HANDLER_FMT(TPM2B_PUBLIC), ADD_HANDLER_FMT(TPMT_PUBLIC) }; size_t i; for (i=0; i < ARRAY_LEN(handlers); i++) { if (!strcmp(name, handlers[i].name)) { if (ctx.format_set && !(handlers[i].flags & FLAG_FMT)) { LOG_ERR("Cannot specify --format/-f with handler for type \"%s\"", name); return false; } ctx.file.handler = handlers[i].fn; return true; } } LOG_ERR("Unknown file type, got: \"%s\"", name); return false; } static bool on_option(char key, char *value) { switch (key) { case 't': return handle_type(value); case 'i': ctx.file.path = value; break; case 'f': ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.format == pubkey_format_err) { return false; } ctx.format_set = true; break; default: LOG_ERR("Invalid option %c", key); return false; } return true; } static bool on_arg(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Expected single file path argument"); return false; } ctx.file.path = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "type", required_argument, NULL, 't' }, { "format", required_argument, NULL, 'f' }, }; *opts = tpm2_options_new("t:f:", ARRAY_LEN(topts), topts, on_option, on_arg, TPM2_OPTIONS_NO_SAPI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(ectx); UNUSED(flags); FILE* fd = stdin; if (!ctx.file.handler) { /* * TODO: This could be automated by each * type having an interrogation function. If it passes, * then use the associated handler. For now, make -t * mandatory. */ LOG_ERR("Must specify -t/--type"); return tool_rc_general_error; } if (ctx.file.path) { LOG_INFO("Reading from file %s", ctx.file.path); fd = fopen(ctx.file.path, "rb"); if (!fd) { LOG_ERR("Could not open file %s", ctx.file.path); return tool_rc_general_error; } } else { LOG_INFO("Reading from stdin"); } bool res = ctx.file.handler(fd); LOG_INFO("Read %ld bytes from file %s", ftell(fd), ctx.file.path); if (fd != stdin) { fclose(fd); } return res ? tool_rc_success : tool_rc_general_error; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("print", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/misc/tpm2_rc_decode.c000066400000000000000000000024761412464516500205310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "log.h" #include "tpm2_tool.h" #define TPM2_RC_MAX 0xffffffff typedef struct tpm2_rc_ctx tpm2_rc_ctx; struct tpm2_rc_ctx { TSS2_RC rc; }; static tpm2_rc_ctx ctx; static bool str_to_tpm_rc(const char *rc_str, TSS2_RC *rc) { uintmax_t rc_read = 0; char *end_ptr = NULL; rc_read = strtoumax(rc_str, &end_ptr, 0); if (rc_read > TPM2_RC_MAX) { LOG_ERR("invalid TSS2_RC"); return false; } /* apply the TPM2_RC_MAX mask to the possibly larger uintmax_t */ *rc = rc_read & TPM2_RC_MAX; return true; } static bool on_arg(int argc, char **argv) { if (argc != 1) { LOG_ERR("Expected 1 rc code, got: %d", argc); } return str_to_tpm_rc(argv[0], &ctx.rc); } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, TPM2_OPTIONS_NO_SAPI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); UNUSED(ectx); const char *e = Tss2_RC_Decode(ctx.rc); tpm2_tool_output("%s\n", e); return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("rc_decode", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_activatecredential.c000066400000000000000000000241001412464516500215060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct tpm_activatecred_ctx tpm_activatecred_ctx; #define MAX_AUX_SESSIONS 1 // two sessions provided by auth interface #define MAX_SESSIONS 3 struct tpm_activatecred_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } credential_key; //Typically EK struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } credentialed_key; //Typically AK TPM2B_ID_OBJECT credential_blob; const char *credential_blob_path; bool is_credential_blob_specified; TPM2B_ENCRYPTED_SECRET secret; /* * Outputs */ const char *output_file; TPM2B_DIGEST *cert_info_data; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; TPMI_ALG_HASH parameter_hash_algorithm; bool is_command_dispatch; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_activatecred_ctx ctx = { .aux_session_handle[0] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; static tool_rc activate_credential_and_output(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_activatecredential(ectx, &ctx.credentialed_key.object, &ctx.credential_key.object, &ctx.credential_blob, &ctx.secret, &ctx.cert_info_data, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0]); } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ tpm2_tool_output("certinfodata:"); size_t i; for (i = 0; i < ctx.cert_info_data->size; i++) { tpm2_tool_output("%.2x", ctx.cert_info_data->buffer[i]); } tpm2_tool_output("\n"); is_file_op_success = files_save_bytes_to_file(ctx.output_file, ctx.cert_info_data->buffer, ctx.cert_info_data->size); free(ctx.cert_info_data); if (!is_file_op_success) { return tool_rc_general_error; } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static bool read_cert_secret(void) { bool result = false; FILE *fp = fopen(ctx.credential_blob_path, "rb"); if (!fp) { LOG_ERR("Could not open file \"%s\" error: \"%s\"", ctx.credential_blob_path, strerror(errno)); return false; } uint32_t version; result = files_read_header(fp, &version); if (!result) { LOG_ERR("Could not read version header"); goto out; } if (version != 1) { LOG_ERR("Unknown credential format, got %"PRIu32" expected 1", version); goto out; } result = files_read_16(fp, &ctx.credential_blob.size); if (!result) { LOG_ERR("Could not read credential size"); goto out; } result = files_read_bytes(fp, ctx.credential_blob.credential, ctx.credential_blob.size); if (!result) { LOG_ERR("Could not read credential data"); goto out; } result = files_read_16(fp, &ctx.secret.size); if (!result) { LOG_ERR("Could not read secret size"); goto out; } result = files_read_bytes(fp, ctx.secret.secret, ctx.secret.size); if (!result) { LOG_ERR("Could not write secret data"); goto out; } result = true; out: fclose(fp); return result; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ /* Object #1 */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.credential_key.ctx_path, ctx.credential_key.auth_str, &ctx.credential_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* Object #2 */ rc = tpm2_util_object_load_auth(ectx, ctx.credentialed_key.ctx_path, ctx.credentialed_key.auth_str, &ctx.credentialed_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ rc = read_cert_secret() ? tool_rc_success : tool_rc_general_error; if (rc != tool_rc_success) { return rc; } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.credential_key.object.session, ctx.credentialed_key.object.session, ctx.aux_session[0] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static tool_rc check_options(void) { if ((!ctx.credentialed_key.ctx_path) && (!ctx.credential_key.ctx_path) && !ctx.is_credential_blob_specified && !ctx.output_file) { LOG_ERR("Expected options c and C and i and o."); return tool_rc_option_error; } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.credentialed_key.ctx_path = value; break; case 'p': ctx.credentialed_key.auth_str = value; break; case 'C': ctx.credential_key.ctx_path = value; break; case 'P': ctx.credential_key.auth_str = value; break; case 'i': /* logs errors */ ctx.credential_blob_path = value; ctx.is_credential_blob_specified = 1; break; case 'o': ctx.output_file = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { {"credentialedkey-context", required_argument, NULL, 'c'}, {"credentialkey-context", required_argument, NULL, 'C'}, {"credentialedkey-auth", required_argument, NULL, 'p'}, {"credentialkey-auth", required_argument, NULL, 'P'}, {"credential-blob", required_argument, NULL, 'i'}, {"certinfo-data", required_argument, NULL, 'o'}, {"cphash", required_argument, NULL, 0 }, {"rphash", required_argument, NULL, 1 }, {"session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("c:C:p:P:i:o:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { /* opts is unused, avoid compiler warning */ UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = activate_credential_and_output(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.credentialed_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } tmp_rc = tpm2_session_close(&ctx.credential_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("activatecredential", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_certify.c000066400000000000000000000252261412464516500173320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_options.h" typedef struct tpm_certify_ctx tpm_certify_ctx; #define MAX_AUX_SESSIONS 1 // two sessions provided by auth interface #define MAX_SESSIONS 3 struct tpm_certify_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } certified_key; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; TPMI_ALG_HASH halg; tpm2_convert_sig_fmt sig_fmt; TPMT_SIG_SCHEME scheme; /* * Outputs */ struct { char *attest; char *sig; } file_path; TPM2B_ATTEST *certify_info; TPMT_SIGNATURE *signature; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_certify_ctx ctx = { .sig_fmt = signature_format_tss, .aux_session_handle[0] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; static tool_rc certify(ESYS_CONTEXT *ectx) { TPM2B_DATA qualifying_data = { .size = 4, .buffer = { 0x00, 0xff, 0x55,0xaa }, }; /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_certify(ectx, &ctx.certified_key.object, &ctx.signing_key.object, &qualifying_data, &ctx.scheme, &ctx.certify_info, &ctx.signature, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0]); } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ /* serialization is safe here, since it's just a byte array */ is_file_op_success = files_save_bytes_to_file(ctx.file_path.attest, ctx.certify_info->attestationData, ctx.certify_info->size); if (!is_file_op_success) { goto out; } is_file_op_success = tpm2_convert_sig_save(ctx.signature, ctx.sig_fmt, ctx.file_path.sig); if (!is_file_op_success) { goto out; } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } out: free(ctx.certify_info); free(ctx.signature); return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc get_key_type(ESYS_CONTEXT *ectx, ESYS_TR object_handle, TPMI_ALG_PUBLIC *type) { TPM2B_PUBLIC *out_public = NULL; tool_rc rc = tpm2_readpublic(ectx, object_handle, &out_public, NULL, NULL); if (rc != tool_rc_success) { return rc; } *type = out_public->publicArea.type; free(out_public); return tool_rc_success; } static tool_rc set_scheme(ESYS_CONTEXT *ectx, ESYS_TR key_handle, TPMI_ALG_HASH halg, TPMT_SIG_SCHEME *scheme) { TPM2_ALG_ID type; tool_rc rc = get_key_type(ectx, key_handle, &type); if (rc != tool_rc_success) { return rc; } switch (type) { case TPM2_ALG_RSA: scheme->scheme = TPM2_ALG_RSASSA; scheme->details.rsassa.hashAlg = halg; break; case TPM2_ALG_KEYEDHASH: scheme->scheme = TPM2_ALG_HMAC; scheme->details.hmac.hashAlg = halg; break; case TPM2_ALG_ECC: scheme->scheme = TPM2_ALG_ECDSA; scheme->details.ecdsa.hashAlg = halg; break; case TPM2_ALG_SYMCIPHER: default: LOG_ERR("Unknown key type, got: 0x%x", type); return tool_rc_general_error; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ /* Object #1 */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.certified_key.ctx_path, ctx.certified_key.auth_str, &ctx.certified_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* Object #2 */ rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ rc = set_scheme(ectx, ctx.signing_key.object.tr_handle, ctx.halg, &ctx.scheme); if (rc != tool_rc_success) { LOG_ERR("No suitable signing scheme!"); return rc; } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.certified_key.object.session, ctx.signing_key.object.session, ctx.aux_session[0] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static tool_rc check_options(void) { if ((!ctx.certified_key.ctx_path) && (!ctx.signing_key.ctx_path)) { LOG_ERR("Must specify the object to be certified and the signing key."); return tool_rc_option_error; } if (ctx.cp_hash_path && !ctx.rp_hash_path && (ctx.file_path.attest || ctx.file_path.sig)) { LOG_ERR("Cannot specify output options when calculating cpHash"); return tool_rc_option_error; } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.certified_key.ctx_path = value; break; case 'C': ctx.signing_key.ctx_path = value; break; case 'P': ctx.certified_key.auth_str = value; break; case 'p': ctx.signing_key.auth_str = value; break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Could not format algorithm to number, got: \"%s\"", value); return false; } break; case 'o': ctx.file_path.attest = value; break; case 's': ctx.file_path.sig = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'f': ctx.sig_fmt = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_fmt == signature_format_err) { return false; } break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "certifiedkey-context", required_argument, NULL, 'c' }, { "signingkey-context", required_argument, NULL, 'C' }, { "certifiedkey-auth", required_argument, NULL, 'p' }, { "signingkey-auth", required_argument, NULL, 'P' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "attestation", required_argument, NULL, 'o' }, { "signature", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("P:p:g:o:s:c:C:f:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = certify(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.signing_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } tmp_rc = tpm2_session_close(&ctx.certified_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("certify", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_certifycreation.c000066400000000000000000000307771412464516500210660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_options.h" #define MAX_AUX_SESSIONS 2 // one session provided by auth interface #define MAX_SESSIONS 3 typedef struct tpm_certifycreation_ctx tpm_certifycreation_ctx; struct tpm_certifycreation_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; struct { const char *ctx_path; tpm2_loaded_object object; } certified_key; char *creation_hash_path; TPM2B_DIGEST creation_hash; char *creation_ticket_path; TPMT_TK_CREATION creation_ticket; TPM2B_DATA policy_qualifier; const char *policy_qualifier_data; TPMI_ALG_HASH halg; TPMI_ALG_SIG_SCHEME sig_scheme; tpm2_convert_sig_fmt sig_format; TPMT_SIG_SCHEME in_scheme; /* * Outputs */ char *signature_path; TPMT_SIGNATURE *signature; char *certify_info_path; TPM2B_ATTEST *certify_info; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; TPMI_ALG_HASH parameter_hash_algorithm; bool is_command_dispatch; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_certifycreation_ctx ctx = { .halg = TPM2_ALG_NULL, .sig_scheme = TPM2_ALG_NULL, .policy_qualifier = TPM2B_EMPTY_INIT, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc certifycreation(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_certifycreation(ectx, &ctx.signing_key.object, &ctx.certified_key.object, &ctx.creation_hash, &ctx.in_scheme, &ctx.creation_ticket, &ctx.certify_info, &ctx.signature, &ctx.policy_qualifier, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc process_output(void) { /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ is_file_op_success = tpm2_convert_sig_save(ctx.signature, ctx.sig_format, ctx.signature_path); if (!is_file_op_success) { LOG_ERR("Failed saving signature data."); return tool_rc_general_error; } is_file_op_success = files_save_bytes_to_file(ctx.certify_info_path, ctx.certify_info->attestationData, ctx.certify_info->size); if (!is_file_op_success) { LOG_ERR("Failed saving attestation data."); return tool_rc_general_error; } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid signing key/ authorization."); return rc; } rc = tpm2_util_object_load(ectx, ctx.certified_key.ctx_path, &ctx.certified_key.object, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid key specified for certification."); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ /* Load creation hash */ rc = files_load_digest(ctx.creation_hash_path, &ctx.creation_hash) ? tool_rc_success : tool_rc_general_error; if (rc != tool_rc_success) { LOG_ERR("Failed loading creation hash."); return rc; } /* Set signature scheme for key type & Validate chosen scheme */ rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.signing_key.object.tr_handle, &ctx.halg, ctx.sig_scheme, &ctx.in_scheme); if (rc != tool_rc_success) { LOG_ERR("bad signature scheme for key type!"); return rc; } /* Load creation ticket */ rc = files_load_creation_ticket(ctx.creation_ticket_path, &ctx.creation_ticket) ? tool_rc_success : tool_rc_general_error; if (rc != tool_rc_success) { LOG_ERR("Could not load creation ticket from file"); return rc; } /* Qualifier data is optional. If not specified default to 0 */ if (ctx.policy_qualifier_data) { ctx.policy_qualifier.size = sizeof(ctx.policy_qualifier.buffer); rc = tpm2_util_bin_from_hex_or_file(ctx.policy_qualifier_data, &ctx.policy_qualifier.size, ctx.policy_qualifier.buffer) ? tool_rc_success : tool_rc_general_error; if (rc != tool_rc_success) { LOG_ERR("Could not load qualifier data"); return rc; } } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.certified_key.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static bool check_options(void) { if (ctx.cp_hash_path && !ctx.rp_hash_path && (ctx.certify_info_path || ctx.signature_path)) { LOG_ERR("Cannot generate outputs when calculating cpHash."); return false; } if (!ctx.signing_key.ctx_path) { LOG_ERR("Must specify the signing key '-C'."); return false; } if (!ctx.certified_key.ctx_path) { LOG_ERR("Must specify the path of the key to certify '-c'."); return false; } if (!ctx.creation_ticket_path) { LOG_ERR("Must specify the creation ticket path '-t'."); return false; } if (!ctx.signature_path && !ctx.cp_hash_path) { LOG_ERR("Must specify the file path to save signature '-o'"); return false; } if (!ctx.certify_info_path && !ctx.cp_hash_path) { LOG_ERR("Must specify file path to save attestation '--attestation'"); return false; } return true; } static bool set_signature_format(char *value) { ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } return true; } static bool set_signing_scheme(char *value) { ctx.sig_scheme = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.sig_scheme == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } return true; } static bool set_digest_algorithm(char *value) { ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Could not convert to number or lookup algorithm, got: " "\"%s\"", value); return false; } return true; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'C': ctx.signing_key.ctx_path = value; break; case 'P': ctx.signing_key.auth_str = value; break; case 'c': ctx.certified_key.ctx_path = value; break; case 'd': ctx.creation_hash_path = value; break; case 't': ctx.creation_ticket_path = value; break; case 'g': result = set_digest_algorithm(value); goto on_option_out; case 's': result = set_signing_scheme(value); goto on_option_out; case 'f': result = set_signature_format(value); goto on_option_out; case 'o': ctx.signature_path = value; break; case 0: ctx.certify_info_path = value; break; case 1: ctx.cp_hash_path = value; break; case 2: ctx.rp_hash_path = value; break; case 'q': ctx.policy_qualifier_data = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; /* no default */ } on_option_out: return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "signingkey-context", required_argument, NULL, 'C' }, { "signingkey-auth", required_argument, NULL, 'P' }, { "certifiedkey-context", required_argument, NULL, 'c' }, { "creation-hash", required_argument, NULL, 'd' }, { "ticket", required_argument, NULL, 't' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "scheme", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "signature", required_argument, NULL, 'o' }, { "attestation", required_argument, NULL, 0 }, { "qualification", required_argument, NULL, 'q' }, { "cphash", required_argument, NULL, 1 }, { "rphash", required_argument, NULL, 2 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("C:P:c:d:t:g:s:f:o:q:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ bool result = check_options(); if (!result) { return tool_rc_option_error; } /* * 2. Process inputs */ tool_rc rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = certifycreation(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ rc = process_output(); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ Esys_Free(ctx.signature); Esys_Free(ctx.certify_info); /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.signing_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("certifycreation", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_changeauth.c000066400000000000000000000247331412464516500177760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" typedef struct changeauth_ctx changeauth_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 // It's possible that parent auth may not be needed struct changeauth_ctx { /* * Inputs */ struct { const char *ctx; tpm2_loaded_object obj; } parent; struct { const char *auth_current; const char *auth_new; const char *ctx; tpm2_loaded_object obj; tpm2_session *new; /* * Outputs */ const char *out_path; } object; TPM2B_PRIVATE *out_private; const TPM2B_AUTH *new_auth; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static changeauth_ctx ctx = { .parameter_hash_algorithm = TPM2_ALG_ERROR, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc hierarchy_change_auth(ESYS_CONTEXT *ectx) { return tpm2_hierarchy_change_auth(ectx, &ctx.object.obj, ctx.new_auth, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc nv_change_auth(ESYS_CONTEXT *ectx) { return tpm2_nv_change_auth(ectx, &ctx.object.obj, ctx.new_auth, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc object_change_auth(ESYS_CONTEXT *ectx) { if (!ctx.object.out_path) { LOG_ERR("Require private output file path option -r"); return tool_rc_general_error; } return tpm2_object_change_auth(ectx, &ctx.parent.obj, &ctx.object.obj, ctx.new_auth, &ctx.out_private, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc change_authorization(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ tool_rc rc = tool_rc_success; /* invoke the proper changauth command based on object type */ UINT8 tag = (ctx.object.obj.handle & TPM2_HR_RANGE_MASK) >> TPM2_HR_SHIFT; switch (tag) { case TPM2_HT_TRANSIENT: case TPM2_HT_PERSISTENT: rc = object_change_auth(ectx); break; case TPM2_HT_NV_INDEX: rc = nv_change_auth(ectx); break; case TPM2_HT_PERMANENT: rc = hierarchy_change_auth(ectx); break; default: LOG_ERR("Unsupported object type, got: 0x%x", tag); rc = tool_rc_general_error; } return rc; } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.is_command_dispatch && ctx.out_private) { is_file_op_success = files_save_private(ctx.out_private, ctx.object.out_path); free(ctx.out_private); if (!is_file_op_success) { LOG_ERR("Failed to save the sensitive key portion"); return tool_rc_general_error; } } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static inline bool object_needs_parent(tpm2_loaded_object *obj) { TPM2_HC h = obj->handle & TPM2_HR_RANGE_MASK; return (h == TPM2_HR_TRANSIENT) || (h == TPM2_HR_PERSISTENT); } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ tool_rc rc = tpm2_auth_util_from_optarg(ectx, ctx.object.auth_new, &ctx.object.new, true); if (rc != tool_rc_success) { return rc; } ctx.new_auth = tpm2_session_get_auth_value(ctx.object.new); /* * 1.b Add object names and their auth sessions */ /* Note: Old-auth value is ignored when calculating cpHash */ /* Object #1 */ rc = tpm2_util_object_load_auth(ectx, ctx.object.ctx, ctx.object.auth_current, &ctx.object.obj, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } if (ctx.object.obj.tr_handle == ESYS_TR_RH_NULL) { LOG_ERR("Cannot change the null hierarchy authorization"); return tool_rc_general_error; } /* transient objects or persistent objects need parents */ bool load_parent = object_needs_parent(&ctx.object.obj); if (load_parent && !ctx.parent.ctx) { LOG_ERR("Expected parent object information via -C"); return tool_rc_option_error; } /* Object #2 */ if (load_parent) { rc = tpm2_util_object_load(ectx, ctx.parent.ctx, &ctx.parent.obj, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ /* * 4. Configuration for calculating the pHash */ /* 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.object.obj.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return tool_rc_success; } static tool_rc check_options(void) { /* load the object to call changeauth on */ if (!ctx.object.ctx) { LOG_ERR("Expected object information via -c"); return tool_rc_option_error; } if (ctx.cp_hash_path && !ctx.rp_hash_path) { LOG_WARN("Auth not changed. Only cpHash is calculated."); } return tool_rc_success; } static bool on_arg(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Expected 1 new password argument, got: %d", argc); return false; } ctx.object.auth_new = argv[0]; return true; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.object.ctx = value; break; case 'C': ctx.parent.ctx = value; break; case 'p': ctx.object.auth_current = value; break; case 'n': ctx.object.auth_new = value; break; case 'r': ctx.object.out_path = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; /*no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { struct option topts[] = { { "object-auth", required_argument, NULL, 'p' }, { "object-context", required_argument, NULL, 'c' }, { "parent-context", required_argument, NULL, 'C' }, { "private", required_argument, NULL, 'r' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("p:c:C:r:S:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = change_authorization(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.object.new); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } tmp_rc = tpm2_session_close(&ctx.object.obj.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } tmp_rc = tpm2_session_close(&ctx.parent.obj.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("changeauth", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_changeeps.c000066400000000000000000000140361412464516500176170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" #include "tpm2_tool.h" typedef struct changeeps_ctx changeeps_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 struct changeeps_ctx { /* * Inputs */ const char *auth_str; tpm2_session *auth_session; /* * Outputs */ /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static changeeps_ctx ctx = { .parameter_hash_algorithm = TPM2_ALG_ERROR, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { LOG_ERR("Failed to save cpHash"); return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ tool_rc rc = tpm2_auth_util_from_optarg(ectx, ctx.auth_str, &ctx.auth_session, false); if (rc != tool_rc_success) { LOG_ERR("Failed loading platform auth."); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ /* * 4. Configuration for calculating the pHash */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_session, ctx.aux_session[0], ctx.aux_session[1] }; /* * 4.a Determine pHash length and alg */ const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return tool_rc_success; } static tool_rc check_options(void) { if (ctx.cp_hash_path && !ctx.rp_hash_path) { LOG_WARN("EPS not changed. Only cpHash is calculated."); } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session",required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("p:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = tpm2_changeeps(ectx, ctx.auth_session, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("changeeps", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_changepps.c000066400000000000000000000140361412464516500176320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" #include "tpm2_tool.h" typedef struct changepps_ctx changepps_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 struct changepps_ctx { /* * Inputs */ const char *auth_str; tpm2_session *auth_session; /* * Outputs */ /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static changepps_ctx ctx = { .parameter_hash_algorithm = TPM2_ALG_ERROR, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { LOG_ERR("Failed to save cpHash"); return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ tool_rc rc = tpm2_auth_util_from_optarg(ectx, ctx.auth_str, &ctx.auth_session, false); if (rc != tool_rc_success) { LOG_ERR("Failed loading platform auth."); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ /* * 4. Configuration for calculating the pHash */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_session, ctx.aux_session[0], ctx.aux_session[1] }; /* * 4.a Determine pHash length and alg */ const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return tool_rc_success; } static tool_rc check_options(void) { if (ctx.cp_hash_path && !ctx.rp_hash_path) { LOG_WARN("EPS not changed. Only cpHash is calculated."); } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session",required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("p:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = tpm2_changepps(ectx, ctx.auth_session, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("changepps", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_clear.c000066400000000000000000000046501412464516500167510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct clear_ctx clear_ctx; struct clear_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; char *cp_hash_path; }; static clear_ctx ctx = { .auth_hierarchy.ctx_path = "l", }; static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.auth_hierarchy.ctx_path = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify a single auth value"); return false; } if (!argc) { //empty auth return true; } ctx.auth_hierarchy.auth_str = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "auth-hierarchy", no_argument, NULL, 'c' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("c:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_L | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid lockout authorization"); return rc; } if (ctx.cp_hash_path) { LOG_WARN("Generating cpHash. Exiting without executing clear."); TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_clear(ectx, &ctx.auth_hierarchy.object, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } return tpm2_clear(ectx, &ctx.auth_hierarchy.object, NULL); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("clear", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_clearcontrol.c000066400000000000000000000077351412464516500203610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct clearcontrol_ctx clearcontrol_ctx; struct clearcontrol_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPMI_YES_NO disable_clear; char *cp_hash_path; }; static clearcontrol_ctx ctx = { .auth_hierarchy.ctx_path = "p", .disable_clear = 0, }; static tool_rc clearcontrol(ESYS_CONTEXT *ectx) { LOG_INFO("Sending TPM2_ClearControl(%s) disableClear command with auth " "handle %s", ctx.disable_clear ? "SET" : "CLEAR", ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_PLATFORM ? "TPM2_RH_PLATFORM" : "TPM2_RH_LOCKOUT"); if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_clearcontrol(ectx, &ctx.auth_hierarchy.object, ctx.disable_clear, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } return tpm2_clearcontrol(ectx, &ctx.auth_hierarchy.object, ctx.disable_clear, NULL); } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify single set/clear operation as s|c|0|1."); return false; } if (!argc) { LOG_ERR("Disable clear SET/CLEAR operation must be specified."); return false; } if (!strcmp(argv[0], "s")) { ctx.disable_clear = 1; return true; } if (!strcmp(argv[0], "c")) { ctx.disable_clear = 0; return true; } uint32_t value; bool result = tpm2_util_string_to_uint32(argv[0], &value); if (!result) { LOG_ERR("Please specify 0|1|s|c. Could not convert string, got: \"%s\"", argv[0]); return false; } if (value != 0 && value != 1) { LOG_ERR("Please use 0|1|s|c as the argument to specify operation"); return false; } ctx.disable_clear = value; return true; } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_P | TPM2_HANDLE_FLAGS_L); if (rc != tool_rc_success) { LOG_ERR("Invalid authorization"); return rc; } if (!ctx.disable_clear && ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_LOCKOUT) { LOG_ERR("Only platform hierarchy handle can be specified" " for CLEAR operation on disableClear"); return tool_rc_general_error; } if (ctx.cp_hash_path) { LOG_WARN("Calculating cpHash. Exiting without configuring disableClear"); } return clearcontrol(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("clearcontrol", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_clockrateadjust.c000066400000000000000000000062731412464516500210500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_util.h" typedef struct tpm2_setclock_ctx tpm2_setclock_ctx; struct tpm2_setclock_ctx { TPM2_CLOCK_ADJUST adjust; const char *auth_hierarchy; tpm2_loaded_object object; const char *auth_value; char *cp_hash_path; }; static tpm2_setclock_ctx ctx = { .auth_hierarchy = "o" /* default to owner hierarchy */ }; static bool on_arg(int argc, char **argv) { if (argc != 1) { LOG_ERR("Can only specify 1 clock rate adjust specifier, got: %d", argc); return false; } const char *adjustment = argv[0]; size_t len = strlen(adjustment); if (len > 3) { LOG_ERR("Expected at most 3 adjustment characters"); return false; } static const char slower[] = "sss"; static const char faster[] = "fff"; bool is_slower = adjustment[0] == 's'; const char *compare = is_slower ? slower : faster; bool is_equal = !strncmp(adjustment, compare, len); if (!is_equal) { LOG_ERR("Adjustment specifier should be consistent, either all " "'s' or all 'f' characters got: \"%s\"", adjustment); return false; } if (is_slower) { ctx.adjust -= len; } else { ctx.adjust += len; } return true; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.auth_hierarchy = value; break; case 'p': ctx.auth_value = value; break; case 0: ctx.cp_hash_path = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("c:p:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy, ctx.auth_value, &ctx.object, false, TPM2_HANDLE_FLAGS_P|TPM2_HANDLE_FLAGS_O); if (rc != tool_rc_success) { return rc; } LOG_INFO("adjust value: %d", ctx.adjust); if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; LOG_WARN("Calculating cpHash. Exiting without setting clock."); rc = tpm2_clockrateadjust(ectx, &ctx.object, ctx.adjust, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } return tpm2_clockrateadjust(ectx, &ctx.object, ctx.adjust, NULL); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("clockrateadjust", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_commit.c000066400000000000000000000130331412464516500171460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" typedef struct tpm_ecephemeral_ctx tpm_ecephemeral_ctx; struct tpm_ecephemeral_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; char *basepoint_x_coordinate_data_path; char *basepoint_y_data_path; char *eccpoint_M_data_path; char *eccpoint_K_data_path; char *eccpoint_L_data_path; char *eccpoint_E_data_path; char *commit_counter_path; TPM2B_ECC_POINT P1; TPM2B_SENSITIVE_DATA s2; TPM2B_ECC_PARAMETER y2; TPM2B_ECC_POINT *K; TPM2B_ECC_POINT *L; TPM2B_ECC_POINT *E; uint16_t counter; }; static tpm_ecephemeral_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.signing_key.auth_str = value; break; case 'c': ctx.signing_key.ctx_path = value; break; case 0: ctx.basepoint_y_data_path = value; break; case 1: ctx.eccpoint_M_data_path = value; break; case 2: ctx.eccpoint_K_data_path = value; break; case 3: ctx.eccpoint_L_data_path = value; break; case 'u': ctx.eccpoint_E_data_path = value; break; case 't': ctx.commit_counter_path = value; break; }; return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify single argument with file input containing the " "octet array used to derive x-coordinate of a base point"); return false; } ctx.basepoint_x_coordinate_data_path = strcmp("-", argv[0]) ? argv[0] : NULL; return files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.basepoint_x_coordinate_data_path, &ctx.s2.size, ctx.s2.buffer); } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "context", required_argument, NULL, 'c' }, { "basepoint-y", required_argument, NULL, 0 }, { "eccpoint-P", required_argument, NULL, 1 }, { "eccpoint-K", required_argument, NULL, 2 }, { "eccpoint-L", required_argument, NULL, 3 }, { "public", required_argument, NULL, 'u' }, { "counter", required_argument, NULL, 't' }, }; *opts = tpm2_options_new("p:c:t:u:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc check_options(void) { if (!ctx.signing_key.ctx_path) { LOG_ERR("Specify a signing key"); return tool_rc_option_error; } if (ctx.basepoint_y_data_path && !ctx.basepoint_x_coordinate_data_path) { LOG_ERR("Specify parameter data for basepoint X coordinate derivation"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { return rc; } bool result = true; if (ctx.basepoint_x_coordinate_data_path) { result = files_load_ecc_point(ctx.eccpoint_M_data_path, &ctx.P1); } if (!result) { LOG_ERR("Failed to load input ECC point P1"); return tool_rc_general_error; } if (ctx.basepoint_y_data_path) { result = files_load_ecc_parameter(ctx.basepoint_y_data_path, &ctx.y2); } if (!result) { LOG_ERR("Failed to load input ECC parameter y2"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc process_outputs(void) { bool result = files_save_ecc_point(ctx.K, ctx.eccpoint_K_data_path); if (!result) { LOG_ERR("Failed to write out the ECC point K"); return tool_rc_general_error; } result = files_save_ecc_point(ctx.L, ctx.eccpoint_L_data_path); if (!result) { LOG_ERR("Failed to write out the ECC point L"); return tool_rc_general_error; } result = files_save_ecc_point(ctx.E, ctx.eccpoint_E_data_path); if (!result) { LOG_ERR("Failed to write out the ECC point E"); return tool_rc_general_error; } FILE *fp = fopen(ctx.commit_counter_path, "wb"); result = files_write_16(fp, ctx.counter); fclose(fp); if (!result) { LOG_ERR("Failed to write out the ECC commit count"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // Process inputs rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } // ESAPI call rc = tpm2_commit(ectx, &ctx.signing_key.object, &ctx.P1, &ctx.s2, &ctx.y2, &ctx.K, &ctx.L, &ctx.E, &ctx.counter); if (rc != tool_rc_success) { return rc; } // Process outputs rc = process_outputs(); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("commit", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_create.c000066400000000000000000000441611412464516500171270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_convert.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" #include "tpm2_util.h" typedef struct tpm_create_ctx tpm_create_ctx; #define MAX_AUX_SESSIONS 2 #define MAX_SESSIONS 3 struct tpm_create_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } parent; struct { char *sealed_data; char *auth_str; TPM2B_SENSITIVE_CREATE sensitive; TPM2B_PUBLIC in_public; TPM2B_DATA outside_info; TPML_PCR_SELECTION creation_pcr; char *outside_info_data; char *alg; char *attrs; char *name_alg; char *policy; bool is_object_alg_specified; bool is_sealing_input_specified; /* * Outputs */ char *public_path; TPM2B_PUBLIC *out_public; const char *ctx_path; char *private_path; TPM2B_PRIVATE *out_private; char *creation_data_file; TPM2B_CREATION_DATA *creation_data; char *creation_hash_file; TPM2B_DIGEST *creation_hash; char *creation_ticket_file; TPMT_TK_CREATION *creation_ticket; char *template_data_path; ESYS_TR object_handle; } object; bool is_createloaded; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; TPMI_ALG_HASH parameter_hash_algorithm; bool is_command_dispatch; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; /* * Formated public key output */ char *output_path; bool format_set; tpm2_convert_pubkey_fmt format; }; #define DEFAULT_KEY_ALG "rsa2048" static tpm_create_ctx ctx = { .object = { .alg = DEFAULT_KEY_ALG }, .object.creation_pcr = { .count = 0 }, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, .object.object_handle = ESYS_TR_NONE, .cp_hash.size = 0, .is_command_dispatch = true, .object.outside_info.size = 0, .parameter_hash_algorithm = TPM2_ALG_ERROR, .format = pubkey_format_tss, }; static bool load_outside_info(TPM2B_DATA *outside_info) { outside_info->size = sizeof(outside_info->buffer); return tpm2_util_bin_from_hex_or_file(ctx.object.outside_info_data, &outside_info->size, outside_info->buffer); } static tool_rc create(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ /* TPM2_CC_CreateLoaded */ if (ctx.is_createloaded) { size_t offset = 0; TPM2B_TEMPLATE template = { .size = 0 }; tool_rc tmp_rc = tpm2_mu_tpmt_public_marshal( &ctx.object.in_public.publicArea, &template.buffer[0], sizeof(TPMT_PUBLIC), &offset); if (tmp_rc != tool_rc_success) { return tmp_rc; } template.size = offset; tmp_rc = tpm2_create_loaded(ectx, &ctx.parent.object, &ctx.object.sensitive, &template, &ctx.object.object_handle, &ctx.object.out_private, &ctx.object.out_public, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); if (tmp_rc != tool_rc_success) { return tmp_rc; } } /* TPM2_CC_Create */ if (!ctx.is_createloaded) { /* * Outside data is optional. If not specified default to 0 */ bool result = ctx.object.outside_info_data ? load_outside_info(&ctx.object.outside_info) : true; if (!result) { return tool_rc_general_error; } tool_rc tmp_rc = tpm2_create(ectx, &ctx.parent.object, &ctx.object.sensitive, &ctx.object.in_public, &ctx.object.outside_info, &ctx.object.creation_pcr, &ctx.object.out_private, &ctx.object.out_public, &ctx.object.creation_data, &ctx.object.creation_hash, &ctx.object.creation_ticket, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); if (tmp_rc != tool_rc_success) { return tmp_rc; } } return tool_rc_success; } static void setup_attributes(TPMA_OBJECT *attrs) { if (ctx.object.is_sealing_input_specified && !ctx.object.attrs) { *attrs &= ~TPMA_OBJECT_SIGN_ENCRYPT; *attrs &= ~TPMA_OBJECT_DECRYPT; *attrs &= ~TPMA_OBJECT_SENSITIVEDATAORIGIN; } if (!ctx.object.is_sealing_input_specified && !ctx.object.attrs && !strncmp("hmac", ctx.object.alg, 4)) { *attrs &= ~TPMA_OBJECT_DECRYPT; } if (!ctx.object.attrs && ctx.object.policy && !ctx.object.auth_str) { *attrs &= ~TPMA_OBJECT_USERWITHAUTH; } } static tool_rc process_output(ESYS_CONTEXT *ectx) { /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.is_createloaded && ctx.object.template_data_path) { is_file_op_success = files_save_template( &ctx.object.in_public.publicArea, ctx.object.template_data_path); if (!is_file_op_success) { LOG_ERR("Could not save public template to file."); return tool_rc_general_error; } } if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { LOG_ERR("Failed to save cp hash"); return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ /* TPM2_CC_Create outputs */ tool_rc rc = tool_rc_success; if (!ctx.is_createloaded && ctx.object.creation_data_file && ctx.object.creation_data->size) { is_file_op_success = files_save_creation_data(ctx.object.creation_data, ctx.object.creation_data_file); if (!is_file_op_success) { LOG_ERR("Failed saving creation data."); rc = tool_rc_general_error; goto create_out; } } if (!ctx.is_createloaded && ctx.object.creation_ticket_file && ctx.object.creation_ticket->digest.size) { is_file_op_success = files_save_creation_ticket( ctx.object.creation_ticket, ctx.object.creation_ticket_file); if (!is_file_op_success) { LOG_ERR("Failed saving creation ticket."); rc = tool_rc_general_error; goto create_out; } } if (!ctx.is_createloaded && ctx.object.creation_hash_file && ctx.object.creation_hash->size) { is_file_op_success = files_save_digest(ctx.object.creation_hash, ctx.object.creation_hash_file); if (!is_file_op_success) { LOG_ERR("Failed saving creation hash."); rc = tool_rc_general_error; } } if (ctx.output_path) { bool result = tpm2_convert_pubkey_save(ctx.object.out_public, ctx.format, ctx.output_path); if (!result) { LOG_ERR("Failed saving public key."); return tool_rc_general_error; } } create_out: free(ctx.object.creation_data); free(ctx.object.creation_hash); free(ctx.object.creation_ticket); if (rc != tool_rc_success) { return rc; } /* Common- TPM2_CC_Create/ TPM2_CC_CreateLoaded outputs*/ tpm2_util_public_to_yaml(ctx.object.out_public, NULL); if (ctx.object.public_path) { is_file_op_success = files_save_public(ctx.object.out_public, ctx.object.public_path); if (!is_file_op_success) { rc = tool_rc_general_error; goto out; } } if (ctx.object.private_path) { is_file_op_success = files_save_private(ctx.object.out_private, ctx.object.private_path); if (!is_file_op_success) { rc = tool_rc_general_error; goto out; } } if (ctx.object.ctx_path) { rc = files_save_tpm_context_to_path(ectx, ctx.object.object_handle, ctx.object.ctx_path); if (rc != tool_rc_success) { goto out; } } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); if (!is_file_op_success) { rc = tool_rc_general_error; } } out: free(ctx.object.out_private); free(ctx.object.out_public); return rc; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ tpm2_session *tmp; tool_rc rc = tpm2_auth_util_from_optarg(NULL, ctx.object.auth_str, &tmp, true); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } TPM2B_AUTH const *auth = tpm2_session_get_auth_value(tmp); ctx.object.sensitive.sensitive.userAuth = *auth; tpm2_session_close(&tmp); /* * 1.b Add object names and their auth sessions */ rc = tpm2_util_object_load_auth(ectx, ctx.parent.ctx_path, ctx.parent.auth_str, &ctx.parent.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ /* Setup attributes */ TPMA_OBJECT attrs = DEFAULT_CREATE_ATTRS; setup_attributes(&attrs); /* Initialize object */ rc = tpm2_alg_util_public_init(ctx.object.alg, ctx.object.name_alg, ctx.object.attrs, ctx.object.policy, attrs, &ctx.object.in_public); if (rc != tool_rc_success) { return rc; } /* Check object validitity */ if (ctx.object.is_sealing_input_specified && ctx.object.in_public.publicArea.type != TPM2_ALG_KEYEDHASH) { LOG_ERR("Only TPM2_ALG_KEYEDHASH algorithm is allowed when sealing data"); return tool_rc_general_error; } /* Check command type */ if ((ctx.object.ctx_path || ctx.object.template_data_path) && (!ctx.object.creation_data_file && !ctx.object.creation_ticket_file && !ctx.object.creation_hash_file)) { ctx.is_createloaded = true; } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.parent.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static tool_rc check_options(void) { if (!ctx.parent.ctx_path) { LOG_ERR("Must specify parent object via -C."); return tool_rc_option_error; } if (ctx.object.is_sealing_input_specified && ctx.object.is_object_alg_specified) { LOG_ERR("Cannot specify -G and -i together."); return tool_rc_option_error; } if (ctx.cp_hash_path && !ctx.rp_hash_path && (ctx.object.public_path || ctx.object.private_path || ctx.object.creation_data_file || ctx.object.creation_hash_file || ctx.object.creation_ticket_file || ctx.object.ctx_path)) { LOG_ERR("CpHash Error: Cannot specify pub, priv, creation - data, hash, ticket"); return tool_rc_option_error; } if (ctx.format_set && !ctx.output_path) { LOG_ERR("Cannot specify --format/-f without specifying --output/-o"); return tool_rc_option_error; } return tool_rc_success; } static bool load_sensitive(void) { ctx.object.sensitive.sensitive.data.size = BUFFER_SIZE( typeof(ctx.object.sensitive.sensitive.data), buffer); return files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.object.sealed_data, &ctx.object.sensitive.sensitive.data.size, ctx.object.sensitive.sensitive.data.buffer); } static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.parent.auth_str = value; break; case 'p': ctx.object.auth_str = value; break; case 'g': ctx.object.name_alg = value; break; case 'G': ctx.object.alg = value; ctx.object.is_object_alg_specified = true; break; case 'a': ctx.object.attrs = value; break; case 'i': ctx.object.sealed_data = strcmp("-", value) ? value : NULL; ctx.object.alg = "keyedhash"; ctx.object.is_sealing_input_specified = true; bool res = load_sensitive(); if (!res) { return false; } break; case 'L': ctx.object.policy = value; break; case 'u': ctx.object.public_path = value; break; case 'r': ctx.object.private_path = value; break; case 'C': ctx.parent.ctx_path = value; break; case 'c': ctx.object.ctx_path = value; break; case 0: ctx.object.creation_data_file = value; break; case 1: ctx.object.template_data_path = value; break; case 't': ctx.object.creation_ticket_file = value; break; case 'd': ctx.object.creation_hash_file = value; break; case 'q': ctx.object.outside_info_data = value; break; case 'l': if (!pcr_parse_selections(value, &ctx.object.creation_pcr)) { LOG_ERR("Could not parse pcr selections, got: \"%s\"", value); return false; } break; case 2: ctx.cp_hash_path = value; break; case 3: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; case 'f': ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.format == pubkey_format_err) { return false; } ctx.format_set = true; break; case 'o': ctx.output_path = value; break; /* no default */ }; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "parent-auth", required_argument, NULL, 'P' }, { "key-auth", required_argument, NULL, 'p' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "key-algorithm", required_argument, NULL, 'G' }, { "attributes", required_argument, NULL, 'a' }, { "sealing-input", required_argument, NULL, 'i' }, { "policy", required_argument, NULL, 'L' }, { "public", required_argument, NULL, 'u' }, { "private", required_argument, NULL, 'r' }, { "parent-context", required_argument, NULL, 'C' }, { "key-context", required_argument, NULL, 'c' }, { "creation-data", required_argument, NULL, 0 }, { "template-data", required_argument, NULL, 1 }, { "creation-ticket",required_argument, NULL, 't' }, { "creation-hash", required_argument, NULL, 'd' }, { "outside-info", required_argument, NULL, 'q' }, { "pcr-list", required_argument, NULL, 'l' }, { "cphash", required_argument, NULL, 2 }, { "rphash", required_argument, NULL, 3 }, { "session", required_argument, NULL, 'S' }, { "format", required_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("P:p:g:G:a:i:L:u:r:C:c:t:d:q:l:S:o:f:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = create(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.parent.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("create", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_createak.c000066400000000000000000000372501412464516500174440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_convert.h" #include "tpm2_tool.h" typedef struct createak_context createak_context; struct createak_context { struct { const char *ctx_arg; tpm2_loaded_object ek_ctx; tpm2_session *session; char *auth_str; } ek; struct { struct { TPM2B_SENSITIVE_CREATE in_sensitive; struct { TPM2_ALG_ID type; TPM2_ALG_ID digest; TPM2_ALG_ID sign; } alg; } in; struct { const char *ctx_file; tpm2_convert_pubkey_fmt pub_fmt; const char *pub_file; const char *name_file; const char *priv_file; const char *qname_file; } out; char *auth_str; } ak; struct { UINT8 f :1; } flags; }; static createak_context ctx = { .ak = { .in = { .alg = { .type = TPM2_ALG_RSA, .digest = TPM2_ALG_SHA256, .sign = TPM2_ALG_NULL }, }, .out = { .pub_fmt = pubkey_format_tss }, }, .flags = { 0 }, }; /* * TODO: All these set_xxx_signing_algorithm() routines could likely somehow be refactored into one. */ static bool set_rsa_signing_algorithm(UINT32 sign_alg, UINT32 digest_alg, TPM2B_PUBLIC *in_public) { if (sign_alg == TPM2_ALG_NULL) { sign_alg = TPM2_ALG_RSASSA; } in_public->publicArea.parameters.rsaDetail.scheme.scheme = sign_alg; switch (sign_alg) { case TPM2_ALG_RSASSA: case TPM2_ALG_RSAPSS: in_public->publicArea.parameters.rsaDetail.scheme.details.anySig.hashAlg = digest_alg; break; default: LOG_ERR("The RSA signing algorithm type input(%4.4x) is not supported!", sign_alg); return false; } return true; } static bool set_ecc_signing_algorithm(UINT32 sign_alg, UINT32 digest_alg, TPM2B_PUBLIC *in_public) { if (sign_alg == TPM2_ALG_NULL) { sign_alg = TPM2_ALG_ECDSA; } in_public->publicArea.parameters.eccDetail.scheme.scheme = sign_alg; switch (sign_alg) { case TPM2_ALG_ECDSA: case TPM2_ALG_SM2: case TPM2_ALG_ECSCHNORR: case TPM2_ALG_ECDAA: in_public->publicArea.parameters.eccDetail.scheme.details.anySig.hashAlg = digest_alg; break; default: LOG_ERR("The ECC signing algorithm type input(%4.4x) is not supported!", sign_alg); return false; } return true; } static bool set_keyed_hash_signing_algorithm(UINT32 sign_alg, UINT32 digest_alg, TPM2B_PUBLIC *in_public) { if (sign_alg == TPM2_ALG_NULL) { sign_alg = TPM2_ALG_HMAC; } in_public->publicArea.parameters.keyedHashDetail.scheme.scheme = sign_alg; switch (sign_alg) { case TPM2_ALG_HMAC: in_public->publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg = digest_alg; break; default: LOG_ERR( "The Keyedhash signing algorithm type input(%4.4x) is not supported!", sign_alg); return false; } return true; } static bool set_key_algorithm(TPM2B_PUBLIC *in_public) { in_public->publicArea.nameAlg = TPM2_ALG_SHA256; // First clear attributes bit field. in_public->publicArea.objectAttributes = 0; in_public->publicArea.objectAttributes |= TPMA_OBJECT_RESTRICTED; in_public->publicArea.objectAttributes |= TPMA_OBJECT_USERWITHAUTH; in_public->publicArea.objectAttributes |= TPMA_OBJECT_SIGN_ENCRYPT; in_public->publicArea.objectAttributes &= ~TPMA_OBJECT_DECRYPT; in_public->publicArea.objectAttributes |= TPMA_OBJECT_FIXEDTPM; in_public->publicArea.objectAttributes |= TPMA_OBJECT_FIXEDPARENT; in_public->publicArea.objectAttributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN; in_public->publicArea.authPolicy.size = 0; in_public->publicArea.type = ctx.ak.in.alg.type; switch (ctx.ak.in.alg.type) { case TPM2_ALG_RSA: in_public->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM2_ALG_NULL; in_public->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 0; in_public->publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM2_ALG_NULL; in_public->publicArea.parameters.rsaDetail.keyBits = 2048; in_public->publicArea.parameters.rsaDetail.exponent = 0; in_public->publicArea.unique.rsa.size = 0; return set_rsa_signing_algorithm(ctx.ak.in.alg.sign, ctx.ak.in.alg.digest, in_public); case TPM2_ALG_ECC: in_public->publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_NULL; in_public->publicArea.parameters.eccDetail.symmetric.mode.sym = TPM2_ALG_NULL; in_public->publicArea.parameters.eccDetail.symmetric.keyBits.sym = 0; in_public->publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256; in_public->publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; in_public->publicArea.unique.ecc.x.size = 0; in_public->publicArea.unique.ecc.y.size = 0; return set_ecc_signing_algorithm(ctx.ak.in.alg.sign, ctx.ak.in.alg.digest, in_public); case TPM2_ALG_KEYEDHASH: in_public->publicArea.unique.keyedHash.size = 0; return set_keyed_hash_signing_algorithm(ctx.ak.in.alg.sign, ctx.ak.in.alg.digest, in_public); case TPM2_ALG_SYMCIPHER: default: LOG_ERR("The algorithm type input(%4.4x) is not supported!", ctx.ak.in.alg.type); return false; } return true; } static tool_rc create_ak(ESYS_CONTEXT *ectx) { tool_rc rc = tool_rc_general_error; TPML_PCR_SELECTION creation_pcr = { .count = 0 }; TPM2B_DATA outside_info = TPM2B_EMPTY_INIT; TPM2B_PUBLIC *out_public; TPM2B_PRIVATE *out_private; TPM2B_PUBLIC in_public = TPM2B_EMPTY_INIT; bool result = set_key_algorithm(&in_public); if (!result) { return tool_rc_general_error; } tpm2_session_data *data = tpm2_session_data_new(TPM2_SE_POLICY); if (!data) { LOG_ERR("oom"); return tool_rc_general_error; } tpm2_session *session = NULL; tool_rc tmp_rc = tpm2_session_open(ectx, data, &session); if (tmp_rc != tool_rc_success) { LOG_ERR("Could not start tpm session"); return tmp_rc; } LOG_INFO("tpm_session_start_auth_with_params succ"); ESYS_TR sess_handle = tpm2_session_get_handle(session); ESYS_TR shandle = ESYS_TR_NONE; tmp_rc = tpm2_auth_util_get_shandle(ectx, ESYS_TR_RH_ENDORSEMENT, ctx.ek.session, &shandle); if (tmp_rc != tool_rc_success) { rc = tmp_rc; goto out_session; } TPM2_RC rval = Esys_PolicySecret(ectx, ESYS_TR_RH_ENDORSEMENT, sess_handle, shandle, ESYS_TR_NONE, ESYS_TR_NONE, NULL, NULL, NULL, 0, NULL, NULL); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_PolicySecret, rval); goto out_session; } LOG_INFO("Esys_PolicySecret success"); TPM2B_CREATION_DATA *creation_data = NULL; rval = Esys_Create(ectx, ctx.ek.ek_ctx.tr_handle, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE, &ctx.ak.in.in_sensitive, &in_public, &outside_info, &creation_pcr, &out_private, &out_public, &creation_data, NULL, NULL); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Create, rval); goto out; } LOG_INFO("Esys_Create success"); rc = tpm2_session_close(&session); if (rc != tool_rc_success) { goto out; } data = tpm2_session_data_new(TPM2_SE_POLICY); if (!data) { LOG_ERR("oom"); goto out; } tmp_rc = tpm2_session_open(ectx, data, &session); if (tmp_rc != tool_rc_success) { LOG_ERR("Could not start tpm session"); rc = tmp_rc; goto out; } LOG_INFO("tpm_session_start_auth_with_params succ"); sess_handle = tpm2_session_get_handle(session); tmp_rc = tpm2_auth_util_get_shandle(ectx, sess_handle, ctx.ek.session, &shandle); if (tmp_rc != tool_rc_success) { rc = tmp_rc; goto out; } rval = Esys_PolicySecret(ectx, ESYS_TR_RH_ENDORSEMENT, sess_handle, shandle, ESYS_TR_NONE, ESYS_TR_NONE, NULL, NULL, NULL, 0, NULL, NULL); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_PolicySecret, rval); goto out; } LOG_INFO("Esys_PolicySecret success"); ESYS_TR loaded_sha1_key_handle; rval = Esys_Load(ectx, ctx.ek.ek_ctx.tr_handle, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE, out_private, out_public, &loaded_sha1_key_handle); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Load, rval); rc = tool_rc_from_tpm(rval); goto out; } // Load the TPM2 handle so that we can print it TPM2B_NAME *key_name; rval = Esys_TR_GetName(ectx, loaded_sha1_key_handle, &key_name); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_TR_GetName, rval); rc = tool_rc_from_tpm(rval); goto nameout; } rc = tpm2_session_close(&session); if (rc != tool_rc_success) { goto out; } /* generation qualified name */ TPM2B_NAME *p_qname = &creation_data->creationData.parentQualifiedName; TPM2B_NAME qname = { 0 }; rc = tpm2_calq_qname(p_qname, in_public.publicArea.nameAlg, key_name, &qname) ? tool_rc_success : tool_rc_general_error; if (rc != tool_rc_success) { goto out; } /* Output in YAML format */ tpm2_tool_output("loaded-key:\n name: "); tpm2_util_print_tpm2b(key_name); tpm2_tool_output("\n"); tpm2_tool_output(" qualified name: "); tpm2_util_print_tpm2b(&qname); tpm2_tool_output("\n"); // write name to ak.name file if (ctx.ak.out.name_file) { result = files_save_bytes_to_file(ctx.ak.out.name_file, key_name->name, key_name->size); if (!result) { LOG_ERR("Failed to save AK name into file \"%s\"", ctx.ak.out.name_file); goto nameout; } } if (ctx.ak.out.qname_file) { result = files_save_bytes_to_file(ctx.ak.out.qname_file, qname.name, qname.size); if (!result) { LOG_ERR("Failed to save AK qualified name into file \"%s\"", ctx.ak.out.name_file); goto nameout; } } // If the AK isn't persisted we always save a context file of the // transient AK handle for future tool interactions. tmp_rc = files_save_tpm_context_to_path(ectx, loaded_sha1_key_handle, ctx.ak.out.ctx_file); if (tmp_rc != tool_rc_success) { rc = tmp_rc; LOG_ERR("Error saving tpm context for handle"); goto nameout; } if (ctx.ak.out.pub_file) { result = tpm2_convert_pubkey_save(out_public, ctx.ak.out.pub_fmt, ctx.ak.out.pub_file); if (!result) { goto nameout; } } if (ctx.ak.out.priv_file) { result = files_save_private(out_private, ctx.ak.out.priv_file); if (!result) { goto nameout; } } rc = tool_rc_success; nameout: free(key_name); out: free(out_public); free(out_private); Esys_Free(creation_data); out_session: tpm2_session_close(&session); return rc; } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.ek.ctx_arg = value; break; case 'G': ctx.ak.in.alg.type = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_base); if (ctx.ak.in.alg.type == TPM2_ALG_ERROR) { LOG_ERR("Could not convert algorithm. got: \"%s\".", value); return false; } break; case 'g': ctx.ak.in.alg.digest = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.ak.in.alg.digest == TPM2_ALG_ERROR) { LOG_ERR("Could not convert digest algorithm."); return false; } break; case 's': ctx.ak.in.alg.sign = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.ak.in.alg.sign == TPM2_ALG_ERROR) { LOG_ERR("Could not convert signing algorithm."); return false; } break; case 'P': ctx.ek.auth_str = value; break; case 'p': ctx.ak.auth_str = value; break; case 'u': ctx.ak.out.pub_file = value; break; case 'n': ctx.ak.out.name_file = value; break; case 'f': ctx.ak.out.pub_fmt = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.ak.out.pub_fmt == pubkey_format_err) { return false; } ctx.flags.f = true; break; case 'c': ctx.ak.out.ctx_file = value; break; case 'r': ctx.ak.out.priv_file = value; break; case 'q': ctx.ak.out.qname_file = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "eh-auth", required_argument, NULL, 'P' }, { "ak-auth", required_argument, NULL, 'p' }, { "ek-context", required_argument, NULL, 'C' }, { "ak-context", required_argument, NULL, 'c' }, { "ak-name", required_argument, NULL, 'n' }, { "key-algorithm", required_argument, NULL, 'G' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "signing-algorithm", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "public", required_argument, NULL, 'u' }, { "private", required_argument, NULL, 'r' }, { "ak-qualified-name", required_argument, NULL, 'q' }, }; *opts = tpm2_options_new("P:p:C:c:n:G:g:s:f:u:r:q:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (ctx.flags.f && !ctx.ak.out.pub_file) { LOG_ERR("Please specify an output file name when specifying a format"); return tool_rc_option_error; } if (!ctx.ak.out.ctx_file) { LOG_ERR("Expected option -c"); return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load(ectx, ctx.ek.ctx_arg, &ctx.ek.ek_ctx, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } if (!ctx.ek.ek_ctx.tr_handle) { rc = tpm2_util_sys_handle_to_esys_handle(ectx, ctx.ek.ek_ctx.handle, &ctx.ek.ek_ctx.tr_handle); if (rc != tool_rc_success) { LOG_ERR("Converting ek_ctx TPM2_HANDLE to ESYS_TR"); return rc; } } rc = tpm2_auth_util_from_optarg(NULL, ctx.ek.auth_str, &ctx.ek.session, true); if (rc != tool_rc_success) { LOG_ERR("Invalid endorse authorization"); return rc; } tpm2_session *tmp; rc = tpm2_auth_util_from_optarg(NULL, ctx.ak.auth_str, &tmp, true); if (rc != tool_rc_success) { LOG_ERR("Invalid AK authorization"); return rc; } const TPM2B_AUTH *auth = tpm2_session_get_auth_value(tmp); ctx.ak.in.in_sensitive.sensitive.userAuth = *auth; tpm2_session_close(&tmp); return create_ak(ectx); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("createak", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_createek.c000066400000000000000000000324541412464516500174510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_ctx_mgmt.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" #define RSA_EK_NONCE_NV_INDEX 0x01c00003 #define RSA_EK_TEMPLATE_NV_INDEX 0x01c00004 #define ECC_EK_NONCE_NV_INDEX 0x01c0000b #define ECC_EK_TEMPLATE_NV_INDEX 0x01c0000c typedef struct createek_context createek_context; struct createek_context { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_owner_hierarchy; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_endorse_hierarchy; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_ek; tpm2_hierarchy_pdata objdata; char *out_file_path; tpm2_convert_pubkey_fmt format; struct { UINT8 f :1; UINT8 t :1; } flags; bool find_persistent_handle; }; static createek_context ctx = { .format = pubkey_format_tss, .objdata = TPM2_HIERARCHY_DATA_INIT, .flags = { 0 }, .find_persistent_handle = false }; static bool set_key_algorithm(TPM2B_PUBLIC *input_public) { switch (input_public->publicArea.type) { case TPM2_ALG_RSA: input_public->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM2_ALG_AES; input_public->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; input_public->publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM2_ALG_CFB; input_public->publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL; input_public->publicArea.parameters.rsaDetail.keyBits = 2048; input_public->publicArea.parameters.rsaDetail.exponent = 0; input_public->publicArea.unique.rsa.size = 256; break; case TPM2_ALG_KEYEDHASH: input_public->publicArea.parameters.keyedHashDetail.scheme.scheme = TPM2_ALG_XOR; input_public->publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.hashAlg = TPM2_ALG_SHA256; input_public->publicArea.parameters.keyedHashDetail.scheme.details.exclusiveOr.kdf = TPM2_ALG_KDF1_SP800_108; input_public->publicArea.unique.keyedHash.size = 0; break; case TPM2_ALG_ECC: input_public->publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_AES; input_public->publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; input_public->publicArea.parameters.eccDetail.symmetric.mode.sym = TPM2_ALG_CFB; input_public->publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL; input_public->publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256; input_public->publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; input_public->publicArea.unique.ecc.x.size = 32; input_public->publicArea.unique.ecc.y.size = 32; break; case TPM2_ALG_SYMCIPHER: input_public->publicArea.parameters.symDetail.sym.algorithm = TPM2_ALG_AES; input_public->publicArea.parameters.symDetail.sym.keyBits.aes = 128; input_public->publicArea.parameters.symDetail.sym.mode.sym = TPM2_ALG_CFB; input_public->publicArea.unique.sym.size = 0; break; default: LOG_ERR("The algorithm type input(%4.4x) is not supported!", input_public->publicArea.type); return false; } return true; } static tool_rc set_ek_template(ESYS_CONTEXT *ectx, TPM2B_PUBLIC *input_public) { TPM2_HANDLE template_nv_index; TPM2_HANDLE nonce_nv_index; switch (input_public->publicArea.type) { case TPM2_ALG_RSA: template_nv_index = RSA_EK_TEMPLATE_NV_INDEX; nonce_nv_index = RSA_EK_NONCE_NV_INDEX; break; case TPM2_ALG_ECC: template_nv_index = ECC_EK_TEMPLATE_NV_INDEX; nonce_nv_index = ECC_EK_NONCE_NV_INDEX; break; default: LOG_ERR("EK template and EK nonce for algorithm type input(%4.4x)" " are not supported!", input_public->publicArea.type); return tool_rc_general_error; } UINT8* template = NULL; UINT8* nonce = NULL; // Read EK template UINT16 template_size = 0; TPM2B_DIGEST cp_hash = { 0 }; TPM2B_DIGEST rp_hash = { 0 }; tool_rc rc = tpm2_util_nv_read(ectx, template_nv_index, 0, 0, &ctx.auth_owner_hierarchy.object, &template, &template_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0, ESYS_TR_NONE, ESYS_TR_NONE); if (rc != tool_rc_success) { goto out; } TSS2_RC ret = Tss2_MU_TPMT_PUBLIC_Unmarshal(template, template_size, NULL, &input_public->publicArea); if (ret != TPM2_RC_SUCCESS) { LOG_ERR("Failed to unmarshal TPMT_PUBLIC from buffer 0x%p", template); rc = tool_rc_general_error; goto out; } // Read EK nonce UINT16 nonce_size = 0; rc = tpm2_util_nv_read(ectx, nonce_nv_index, 0, 0, &ctx.auth_owner_hierarchy.object, &nonce, &nonce_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0, ESYS_TR_NONE, ESYS_TR_NONE); if (rc != tool_rc_success) { goto out; } if (input_public->publicArea.type == TPM2_ALG_RSA) { memcpy(&input_public->publicArea.unique.rsa.buffer, &nonce, nonce_size); input_public->publicArea.unique.rsa.size = 256; } else { // ECC is only other supported algorithm memcpy(&input_public->publicArea.unique.ecc.x.buffer, &nonce, nonce_size); input_public->publicArea.unique.ecc.x.size = 32; input_public->publicArea.unique.ecc.y.size = 32; } out: if (template) { free(template); } if (nonce) { free(nonce); } return rc; } static tool_rc create_ek_handle(ESYS_CONTEXT *ectx) { if (ctx.flags.t) { tool_rc rc = set_ek_template(ectx, &ctx.objdata.in.public); if (rc != tool_rc_success) { return rc; } } else { bool result = set_key_algorithm(&ctx.objdata.in.public); if (!result) { return tool_rc_general_error; } } tool_rc rc = tpm2_hierarchy_create_primary(ectx, ctx.auth_endorse_hierarchy.object.session, &ctx.objdata, NULL); if (rc != tool_rc_success) { return rc; } if (ctx.auth_ek.object.handle) { rc = tpm2_ctx_mgmt_evictcontrol(ectx, ESYS_TR_RH_OWNER, ctx.auth_owner_hierarchy.object.session, ctx.objdata.out.handle, ctx.auth_ek.object.handle, NULL); if (rc != tool_rc_success) { return rc; } rc = tpm2_flush_context(ectx, ctx.objdata.out.handle); if (rc != tool_rc_success) { return rc; } } else { /* If it wasn't persistent, save a context for future tool interactions */ tool_rc rc = files_save_tpm_context_to_path(ectx, ctx.objdata.out.handle, ctx.auth_ek.ctx_path); if (rc != tool_rc_success) { LOG_ERR("Error saving tpm context for handle"); return rc; } } if (ctx.out_file_path) { bool ok = tpm2_convert_pubkey_save(ctx.objdata.out.public, ctx.format, ctx.out_file_path); if (!ok) { return tool_rc_general_error; } } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.auth_endorse_hierarchy.auth_str = value; break; case 'w': ctx.auth_owner_hierarchy.auth_str = value; break; case 'p': ctx.auth_ek.auth_str = value; break; case 'G': { TPMI_ALG_PUBLIC type = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_base); if (type == TPM2_ALG_ERROR) { LOG_ERR("Invalid key algorithm, got \"%s\"", value); return false; } ctx.objdata.in.public.publicArea.type = type; } break; case 'u': if (!value) { LOG_ERR("Please specify an output file to save the pub ek to."); return false; } ctx.out_file_path = value; break; case 'f': ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.format == pubkey_format_err) { return false; } ctx.flags.f = true; break; case 'c': ctx.auth_ek.ctx_path = value; break; case 't': ctx.flags.t = true; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "eh-auth", required_argument, NULL, 'P' }, { "owner-auth", required_argument, NULL, 'w' }, { "key-algorithm", required_argument, NULL, 'G' }, { "public", required_argument, NULL, 'u' }, { "format", required_argument, NULL, 'f' }, { "ek-context", required_argument, NULL, 'c' }, { "template", no_argument, NULL, 't' }, }; *opts = tpm2_options_new("P:w:G:u:f:c:t", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static void set_default_obj_attrs(void) { ctx.objdata.in.public.publicArea.objectAttributes = TPMA_OBJECT_RESTRICTED | TPMA_OBJECT_ADMINWITHPOLICY | TPMA_OBJECT_DECRYPT | TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN; } static void set_default_auth_policy(void) { static const TPM2B_DIGEST auth_policy = { .size = 32, .buffer = { 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 } }; TPM2B_DIGEST *authp = &ctx.objdata.in.public.publicArea.authPolicy; *authp = auth_policy; } static void set_default_hierarchy(void) { ctx.objdata.in.hierarchy = TPM2_RH_ENDORSEMENT; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); size_t i; tool_rc rc = tool_rc_general_error; tpm2_session **sessions[] = { #if 0 &ctx.auth.ek.session, &ctx.auth.endorse.session, &ctx.auth.owner.session, #endif &ctx.auth_owner_hierarchy.object.session, &ctx.auth_endorse_hierarchy.object.session, &ctx.auth_ek.object.session, }; if (ctx.flags.f && !ctx.out_file_path) { LOG_ERR("Please specify an output file name when specifying a format"); return tool_rc_option_error; } if (!ctx.auth_ek.ctx_path) { LOG_ERR("Expected option -c"); return tool_rc_option_error; } bool ret; if (!strcmp(ctx.auth_ek.ctx_path, "-")) { /* If user passes a handle of '-' we try and find a vacant slot for * to use and tell them what it is. */ rc = tpm2_capability_find_vacant_persistent_handle(ectx, false, &ctx.auth_ek.object.handle); if (rc != tool_rc_success) { LOG_ERR("handle/-H passed with a value '-' but unable to find a" " vacant persistent handle!"); goto out; } tpm2_tool_output("persistent-handle: 0x%x\n", ctx.auth_ek.object.handle); } else { /* best attempt to convert what they have us to a handle, if it's not * a handle then we assume its a path to a context file */ ret = tpm2_util_string_to_uint32(ctx.auth_ek.ctx_path, &ctx.auth_ek.object.handle); UNUSED(ret); } rc = tpm2_util_object_load_auth(ectx, "owner", ctx.auth_owner_hierarchy.auth_str, &ctx.auth_owner_hierarchy.object, false, TPM2_HANDLE_FLAGS_O); if (rc != tool_rc_success) { LOG_ERR("Invalid owner hierarchy authorization"); return rc; } rc = tpm2_util_object_load_auth(ectx, "endorsement", ctx.auth_endorse_hierarchy.auth_str, &ctx.auth_endorse_hierarchy.object, false, TPM2_HANDLE_FLAGS_E); if (rc != tool_rc_success) { LOG_ERR("Invalid endorsement hierarchy authorization"); return rc; } /* * The ek object is created @create_ek_handle and so it isn't loaded here * The ek object attributes are setup to policy reference eh-auth */ rc = tpm2_auth_util_from_optarg(ectx, ctx.auth_ek.auth_str, &ctx.auth_ek.object.session, false); if (rc != tool_rc_success) { LOG_ERR("Invalid EK authorization"); goto out; } /* override the default attrs */ set_default_obj_attrs(); /* set the auth policy */ set_default_auth_policy(); /* set the default hierarchy */ set_default_hierarchy(); /* normalize 0 success 1 failure */ rc = create_ek_handle(ectx); out: for (i = 0; i < ARRAY_LEN(sessions); i++) { tpm2_session *s = *sessions[i]; tool_rc tmp_rc = tpm2_session_close(&s); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } return rc; } static void tpm2_tool_onexit(void) { tpm2_hierarchy_pdata_free(&ctx.objdata); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("createek", tpm2_tool_onstart, tpm2_tool_onrun, NULL, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_createpolicy.c000066400000000000000000000126771412464516500203560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2_alg_util.h" #include "tpm2_policy.h" #include "tpm2_tool.h" //Records the type of policy and if one is selected typedef struct { bool policy_pcr; } policy_type; //Common policy options typedef struct tpm2_common_policy_options tpm2_common_policy_options; struct tpm2_common_policy_options { tpm2_session *policy_session; // policy session TPM2_SE policy_session_type; // TPM2_SE_TRIAL or TPM2_SE_POLICY TPM2B_DIGEST *policy_digest; // buffer to hold policy digest TPMI_ALG_HASH policy_digest_hash_alg; // hash alg of final policy digest char *policy_file; // filepath for the policy digest bool policy_file_flag; // if policy file input has been given policy_type policy_type; const char *context_file; }; //pcr policy options typedef struct tpm2_pcr_policy_options tpm2_pcr_policy_options; struct tpm2_pcr_policy_options { char *raw_pcrs_file; // filepath of input raw pcrs file TPML_PCR_SELECTION pcr_selections; // records user pcr selection per setlist }; typedef struct create_policy_ctx create_policy_ctx; struct create_policy_ctx { tpm2_common_policy_options common_policy_options; tpm2_pcr_policy_options pcr_policy_options; }; #define TPM2_COMMON_POLICY_INIT { \ .policy_session = NULL, \ .policy_session_type = TPM2_SE_TRIAL, \ .policy_digest = NULL, \ .policy_digest_hash_alg = TPM2_ALG_SHA256, \ } static create_policy_ctx pctx = { .common_policy_options = TPM2_COMMON_POLICY_INIT }; static tool_rc parse_policy_type_specific_command(ESYS_CONTEXT *ectx) { if (!pctx.common_policy_options.policy_type.policy_pcr) { LOG_ERR("Only PCR policy is currently supported!"); return tool_rc_option_error; } tpm2_session_data *session_data =tpm2_session_data_new( pctx.common_policy_options.policy_session_type); if (!session_data) { LOG_ERR("oom"); return tool_rc_general_error; } tpm2_session_set_authhash(session_data, pctx.common_policy_options.policy_digest_hash_alg); tpm2_session **s = &pctx.common_policy_options.policy_session; tool_rc rc = tpm2_session_open(ectx, session_data, s); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_pcr(ectx, pctx.common_policy_options.policy_session, pctx.pcr_policy_options.raw_pcrs_file, &pctx.pcr_policy_options.pcr_selections, NULL); if (rc != tool_rc_success) { LOG_ERR("Could not build pcr policy"); return rc; } rc = tpm2_policy_get_digest(ectx, pctx.common_policy_options.policy_session, &pctx.common_policy_options.policy_digest); if (rc != tool_rc_success) { LOG_ERR("Could not build tpm policy"); return rc; } return tpm2_policy_tool_finish(ectx, pctx.common_policy_options.policy_session, pctx.common_policy_options.policy_file); } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': pctx.common_policy_options.policy_file_flag = true; pctx.common_policy_options.policy_file = value; break; case 'f': pctx.pcr_policy_options.raw_pcrs_file = value; break; case 'g': pctx.common_policy_options.policy_digest_hash_alg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (pctx.common_policy_options.policy_digest_hash_alg == TPM2_ALG_ERROR) { LOG_ERR("Invalid choice for policy digest hash algorithm"); return false; } break; case 'l': result = pcr_parse_selections(value, &pctx.pcr_policy_options.pcr_selections); if (!result) { LOG_ERR("Failed to parse PCR string %s", value); return false; } break; case 0: pctx.common_policy_options.policy_type.policy_pcr = true; break; case 1: pctx.common_policy_options.policy_session_type = TPM2_SE_POLICY; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "policy-algorithm", required_argument, NULL, 'g' }, { "pcr-list", required_argument, NULL, 'l' }, { "pcr", required_argument, NULL, 'f' }, { "policy-pcr", no_argument, NULL, 0 }, { "policy-session", no_argument, NULL, 1 }, }; *opts = tpm2_options_new("L:g:l:f:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (pctx.common_policy_options.policy_file_flag == false && pctx.common_policy_options.policy_session_type == TPM2_SE_TRIAL) { LOG_ERR("Provide the file name to store the resulting " "policy digest"); return tool_rc_option_error; } return parse_policy_type_specific_command(ectx); } static void tpm2_tool_onexit(void) { free(pctx.common_policy_options.policy_digest); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("createpolicy", tpm2_tool_onstart, tpm2_tool_onrun, NULL, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_createprimary.c000066400000000000000000000240711412464516500205310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_convert.h" #include "tpm2_hierarchy.h" #include "tpm2_options.h" #define DEFAULT_ATTRS \ TPMA_OBJECT_RESTRICTED|TPMA_OBJECT_DECRYPT \ |TPMA_OBJECT_FIXEDTPM|TPMA_OBJECT_FIXEDPARENT \ |TPMA_OBJECT_SENSITIVEDATAORIGIN|TPMA_OBJECT_USERWITHAUTH #define DEFAULT_PRIMARY_KEY_ALG "rsa2048:null:aes128cfb" typedef struct tpm_createprimary_ctx tpm_createprimary_ctx; struct tpm_createprimary_ctx { struct { char *auth_str; tpm2_session *session; } parent; tpm2_hierarchy_pdata objdata; char *context_file; char *unique_file; char *key_auth_str; char *creation_data_file; char *creation_ticket_file; char *creation_hash_file; char *outside_info_data; char *template_data_path; char *alg; char *halg; char *attrs; char *policy; char *cp_hash_path; char *output_path; bool format_set; tpm2_convert_pubkey_fmt format; }; static tpm_createprimary_ctx ctx = { .alg = DEFAULT_PRIMARY_KEY_ALG, .objdata = { .in = { .sensitive = TPM2B_SENSITIVE_CREATE_EMPTY_INIT, .hierarchy = TPM2_RH_OWNER }, }, .format = pubkey_format_tss, }; static bool on_option(char key, char *value) { bool res; switch (key) { case 'C': { res = tpm2_util_handle_from_optarg(value, &ctx.objdata.in.hierarchy, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); if (!res) { return false; } break; } case 'P': ctx.parent.auth_str = value; break; case 'p': ctx.key_auth_str = value; break; case 'g': ctx.halg = value; break; case 'G': ctx.alg = value; break; case 'c': ctx.context_file = value; break; case 'u': ctx.unique_file = value; break; case 'L': ctx.policy = value; break; case 'a': ctx.attrs = value; break; case 0: ctx.creation_data_file = value; break; case 1: ctx.template_data_path = value; break; case 't': ctx.creation_ticket_file = value; break; case 'd': ctx.creation_hash_file = value; break; case 'q': ctx.outside_info_data = value; break; case 'l': if (!pcr_parse_selections(value, &ctx.objdata.in.creation_pcr)) { LOG_ERR("Could not parse pcr selections, got: \"%s\"", value); return false; } break; case 2: ctx.cp_hash_path = value; break; case 'f': ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.format == pubkey_format_err) { return false; } ctx.format_set = true; break; case 'o': ctx.output_path = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "hierarchy-auth", required_argument, NULL, 'P' }, { "key-auth", required_argument, NULL, 'p' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "key-algorithm", required_argument, NULL, 'G' }, { "key-context", required_argument, NULL, 'c' }, { "policy", required_argument, NULL, 'L' }, { "attributes", required_argument, NULL, 'a' }, { "unique-data", required_argument, NULL, 'u' }, { "creation-data", required_argument, NULL, 0 }, { "template-data", required_argument, NULL, 1 }, { "creation-ticket",required_argument, NULL, 't' }, { "creation-hash", required_argument, NULL, 'd' }, { "outside-info", required_argument, NULL, 'q' }, { "pcr-list", required_argument, NULL, 'l' }, { "cphash", required_argument, NULL, 2 }, { "format", required_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("C:P:p:g:G:c:L:a:u:t:d:q:l:o:f:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc validate_input_options(void) { if (ctx.cp_hash_path && (ctx.creation_data_file || ctx.creation_hash_file || ctx.creation_ticket_file || ctx.context_file)) { LOG_ERR("Cannot generate outputs when calculating cpHash"); return tool_rc_option_error; } if (ctx.format_set && !ctx.output_path) { LOG_ERR("Cannot specify --format/-f without specifying --output/-o"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* Parent/ Hierarchy Auth */ tool_rc rc = tpm2_auth_util_from_optarg(ectx, ctx.parent.auth_str, &ctx.parent.session, false); if (rc != tool_rc_success) { LOG_ERR("Invalid parent key authorization"); return rc; } /* Primary key auth */ tpm2_session *tmp; rc = tpm2_auth_util_from_optarg(NULL, ctx.key_auth_str, &tmp, true); if (rc != tool_rc_success) { LOG_ERR("Invalid new key authorization"); return rc; } const TPM2B_AUTH *auth = tpm2_session_get_auth_value(tmp); ctx.objdata.in.sensitive.sensitive.userAuth = *auth; tpm2_session_close(&tmp); /* * Initialize the public properties of the key */ rc = tpm2_alg_util_public_init(ctx.alg, ctx.halg, ctx.attrs, ctx.policy, DEFAULT_ATTRS, &ctx.objdata.in.public); if (rc != tool_rc_success) { return rc; } /* Optional unique data */ if (ctx.unique_file) { if (!strcmp(ctx.unique_file, "-")) { ctx.unique_file = 0; } rc = files_load_unique_data(ctx.unique_file, &ctx.objdata.in.public); if (rc != tool_rc_success) { return rc; } } /* Outside data is optional. If not specified default to 0 */ if (ctx.outside_info_data) { ctx.objdata.in.outside_info.size = sizeof(ctx.objdata.in.outside_info.buffer); bool result = tpm2_util_bin_from_hex_or_file(ctx.outside_info_data, &ctx.objdata.in.outside_info.size, ctx.objdata.in.outside_info.buffer); if (!result) { return tool_rc_general_error; } } /* * Template saved regardless of execution of the TPM2_CC_CreatePrimary. * * TODO: Does this need to be part of the no_execute_only_process_params * along side processing cphash. * */ if (ctx.template_data_path) { bool result = files_save_template(&ctx.objdata.in.public.publicArea, ctx.template_data_path); if (!result) { LOG_ERR("Could not save public template to file."); return tool_rc_general_error; } } return tool_rc_success; } static tool_rc no_execute_only_process_params(ESYS_CONTEXT *ectx) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_hierarchy_create_primary(ectx, ctx.parent.session, &ctx.objdata, &cp_hash); if (rc == tool_rc_success) { bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { LOG_ERR("Failed to save cp hash"); rc = tool_rc_general_error; } } return rc; } static tool_rc process_outputs(ESYS_CONTEXT *ectx) { tpm2_util_public_to_yaml(ctx.objdata.out.public, NULL); tool_rc rc = ctx.context_file ? files_save_tpm_context_to_path(ectx, ctx.objdata.out.handle, ctx.context_file) : tool_rc_success; if (rc != tool_rc_success) { LOG_ERR("Failed saving object context."); return rc; } bool result = true; if (ctx.creation_data_file) { result = files_save_creation_data(ctx.objdata.out.creation.data, ctx.creation_data_file); } if (!result) { LOG_ERR("Failed saving creation data."); return tool_rc_general_error; } if (ctx.creation_ticket_file) { result = files_save_creation_ticket(ctx.objdata.out.creation.ticket, ctx.creation_ticket_file); } if (!result) { LOG_ERR("Failed saving creation ticket."); return tool_rc_general_error; } if (ctx.creation_hash_file) { result = files_save_digest(ctx.objdata.out.hash, ctx.creation_hash_file); } if (!result) { LOG_ERR("Failed saving creation hash."); return tool_rc_general_error; } if (ctx.output_path) { result = tpm2_convert_pubkey_save(ctx.objdata.out.public, ctx.format, ctx.output_path); if (!result) { LOG_ERR("Failed saving public key."); return tool_rc_general_error; } } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* Validate input options */ tool_rc rc = validate_input_options(); if (rc != tool_rc_success) { return tool_rc_option_error; } /* Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* Process & return uncoditionally if no execute paths are to be executed */ if (ctx.cp_hash_path) { // One of the conditions for no execute return no_execute_only_process_params(ectx); } /* Dispatch TPM2_CC_CreatePrimary */ rc = tpm2_hierarchy_create_primary(ectx, ctx.parent.session, &ctx.objdata, NULL); if (rc != tool_rc_success) { return rc; } /* Process outputs and return */ return process_outputs(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.parent.session); } static void tpm2_tool_onexit(void) { tpm2_hierarchy_pdata_free(&ctx.objdata); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("createprimary", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_dictionarylockout.c000066400000000000000000000151011412464516500214220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" typedef struct dictionarylockout_ctx dictionarylockout_ctx; struct dictionarylockout_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; UINT32 max_tries; UINT32 recovery_time; UINT32 lockout_recovery_time; bool clear_lockout; bool setup_parameters; bool is_setup_max_tries; bool is_setup_recovery_time; bool is_setup_lockoutrecovery_time; char *cp_hash_path; }; static dictionarylockout_ctx ctx = { .auth_hierarchy.ctx_path = "l", }; static bool on_option(char key, char *value) { bool result; switch (key) { case 'c': ctx.clear_lockout = true; break; case 's': ctx.setup_parameters = true; break; case 'p': ctx.auth_hierarchy.auth_str = value; break; case 'n': result = tpm2_util_string_to_uint32(value, &ctx.max_tries); if (!result) { LOG_ERR("Could not convert max_tries to number, got: \"%s\"", value); return false; } if (ctx.max_tries == 0) { return false; } ctx.is_setup_max_tries = true; break; case 't': result = tpm2_util_string_to_uint32(value, &ctx.recovery_time); if (!result) { LOG_ERR("Could not convert recovery_time to number, got: \"%s\"", value); return false; } ctx.is_setup_recovery_time = true; break; case 'l': result = tpm2_util_string_to_uint32(value, &ctx.lockout_recovery_time); if (!result) { LOG_ERR("Could not convert lockout_recovery_time to number, got: " "\"%s\"", value); return false; } ctx.is_setup_lockoutrecovery_time = true; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "max-tries", required_argument, NULL, 'n' }, { "recovery-time", required_argument, NULL, 't' }, { "lockout-recovery-time", required_argument, NULL, 'l' }, { "auth", required_argument, NULL, 'p' }, { "clear-lockout", no_argument, NULL, 'c' }, { "setup-parameters", no_argument, NULL, 's' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("n:t:l:p:cs", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (!ctx.clear_lockout && !ctx.setup_parameters) { LOG_ERR("Invalid operational input: Neither Setup nor Clear lockout " "requested."); return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_L); if (rc != tool_rc_success) { LOG_ERR("Invalid authorization"); return rc; } /* * If calculating cpHash without executing the command, skip reading * existing dictionary lockout parameters. */ if (ctx.setup_parameters && !ctx.cp_hash_path) { TPMS_CAPABILITY_DATA *capabilities = NULL; rc = tpm2_getcap(ectx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_VAR, TPM2_MAX_TPM_PROPERTIES, NULL, &capabilities); if (rc != tool_rc_success) { LOG_ERR("Couldn't read the currently setup parameters."); return rc; } TPMS_TAGGED_PROPERTY *properties = capabilities->data.tpmProperties.tpmProperty; size_t count = capabilities->data.tpmProperties.count; if (!count) { LOG_ERR("Couldn't read the currently setup parameters."); free(capabilities); return tool_rc_general_error; } size_t i; for (i = 0; i < count; i++) { if (!ctx.is_setup_max_tries && properties[i].property == TPM2_PT_MAX_AUTH_FAIL) { ctx.max_tries = properties[i].value; continue; } if (!ctx.is_setup_recovery_time && properties[i].property == TPM2_PT_LOCKOUT_INTERVAL) { ctx.recovery_time = properties[i].value; continue; } if (!ctx.is_setup_lockoutrecovery_time && properties[i].property == TPM2_PT_LOCKOUT_RECOVERY) { ctx.lockout_recovery_time = properties[i].value; continue; } } free(capabilities); } TPM2B_DIGEST cp_hash = { .size = 0 }; if (ctx.cp_hash_path && ctx.clear_lockout) { LOG_WARN("Calculating cpHash. Exiting without resetting dictionary lockout"); tool_rc rc = tpm2_dictionarylockout_reset(ectx, &ctx.auth_hierarchy.object, &cp_hash); if (rc != tool_rc_success) { return rc; } goto out; } if (ctx.cp_hash_path && ctx.setup_parameters) { LOG_WARN("Calculating cpHash. Exiting without setting dictionary lockout"); tool_rc rc = tpm2_dictionarylockout_setup(ectx, &ctx.auth_hierarchy.object, ctx.max_tries, ctx.recovery_time, ctx.lockout_recovery_time, &cp_hash); if (rc != tool_rc_success) { return rc; } goto out; } /* * If setup params and clear lockout are both required, clear lockout should * precede parameters setup. */ if (ctx.clear_lockout) { return tpm2_dictionarylockout_reset(ectx, &ctx.auth_hierarchy.object, NULL); } if (ctx.setup_parameters) { return tpm2_dictionarylockout_setup(ectx, &ctx.auth_hierarchy.object, ctx.max_tries, ctx.recovery_time, ctx.lockout_recovery_time, NULL); } out: if (ctx.cp_hash_path) { bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("dictionarylockout", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_duplicate.c000066400000000000000000000365421412464516500176420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" #include "tpm2_openssl.h" #include "tpm2_identity_util.h" #define DEFAULT_DUPLICATE_ATTRS (TPMA_OBJECT_USERWITHAUTH|TPMA_OBJECT_DECRYPT|TPMA_OBJECT_SIGN_ENCRYPT) typedef struct tpm_duplicate_ctx tpm_duplicate_ctx; struct tpm_duplicate_ctx { struct { const char *ctx_path; const char *auth_str; char *policy_str; tpm2_loaded_object object; } duplicable_key; struct { const char *ctx_path; tpm2_loaded_object object; } new_parent_key; const char *duplicate_key_public_file; const char *duplicate_key_private_file; const char *private_key_file; const char *parent_public_key_file; char *key_type; char *sym_key_in; char *sym_key_out; char *enc_seed_out; struct { UINT16 c :1; UINT16 C :1; UINT16 G :1; UINT16 i :1; UINT16 o :1; UINT16 r :1; UINT16 s :1; UINT16 U :1; UINT16 k :1; UINT16 u :1; } flags; char *cp_hash_path; }; static tpm_duplicate_ctx ctx; static tool_rc do_duplicate(ESYS_CONTEXT *ectx, TPM2B_DATA *in_key, TPMT_SYM_DEF_OBJECT *sym_alg, TPM2B_DATA **out_key, TPM2B_PRIVATE **duplicate, TPM2B_ENCRYPTED_SECRET **encrypted_seed) { if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_duplicate(ectx, &ctx.duplicable_key.object, &ctx.new_parent_key.object, in_key, sym_alg, out_key, duplicate, encrypted_seed, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } return tpm2_duplicate(ectx, &ctx.duplicable_key.object, &ctx.new_parent_key.object, in_key, sym_alg, out_key, duplicate, encrypted_seed, NULL); } static bool on_option(char key, char *value) { switch (key) { case 'p': ctx.duplicable_key.auth_str = value; break; case 'L': ctx.duplicable_key.policy_str = value; break; case 'G': ctx.key_type = value; ctx.flags.G = 1; break; case 'i': ctx.sym_key_in = value; ctx.flags.i = 1; break; case 'o': ctx.sym_key_out = value; ctx.flags.o = 1; break; case 'C': ctx.new_parent_key.ctx_path = value; ctx.flags.C = 1; break; case 'c': ctx.duplicable_key.ctx_path = value; ctx.flags.c = 1; break; case 'r': ctx.duplicate_key_private_file = value; ctx.flags.r = 1; break; case 'u': ctx.duplicate_key_public_file = value; ctx.flags.u = 1; break; case 's': ctx.enc_seed_out = value; ctx.flags.s = 1; break; case 'U': ctx.parent_public_key_file = value; ctx.flags.U = 1; break; case 'k': ctx.private_key_file = value; ctx.flags.k = 1; break; case 0: ctx.cp_hash_path = value; break; default: LOG_ERR("Invalid option"); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "auth", required_argument, NULL, 'p'}, { "policy", required_argument, NULL, 'L'}, { "wrapper-algorithm", required_argument, NULL, 'G'}, { "private", required_argument, NULL, 'r'}, { "public", required_argument, NULL, 'u'}, { "private-key", required_argument, NULL, 'k'}, { "encryptionkey-in", required_argument, NULL, 'i'}, { "encryptionkey-out", required_argument, NULL, 'o'}, { "encrypted-seed", required_argument, NULL, 's'}, { "parent-context", required_argument, NULL, 'C'}, { "parent-public", required_argument, NULL, 'U'}, { "key-context", required_argument, NULL, 'c'}, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("p:L:G:i:C:o:s:r:c:U:k:u:", ARRAY_LEN(topts), topts, on_option, NULL, TPM2_OPTIONS_OPTIONAL_SAPI); return *opts != NULL; } /** * Check all options and report as many errors as possible via LOG_ERR. * @return * true on success, false on failure. */ static bool check_options(void) { bool result = true; /* Check for NULL alg & (keyin | keyout) */ if (ctx.flags.G == 0) { LOG_ERR("Expected key type to be specified via \"-G\"," " missing option."); result = false; } /* If -G is not "null" we need an encryption key */ if (strcmp(ctx.key_type, "null") && !ctx.flags.U) { if ((ctx.flags.i == 0) && (ctx.flags.o == 0)) { LOG_ERR("Expected in or out encryption key file \"-i/o\"," " missing option."); result = false; } if (ctx.flags.i && ctx.flags.o) { LOG_ERR("Expected either in or out encryption key file \"-i/o\"," " conflicting options."); result = false; } } else { if (ctx.flags.i || ctx.flags.o) { LOG_ERR("Expected neither in nor out encryption key file \"-i/o\"," " conflicting options."); result = false; } } if (ctx.flags.U != ctx.flags.k) { LOG_ERR("Conflicting options: remote public key and local private key must both be specified"); result = false; } else if (!ctx.flags.U) { if (ctx.flags.C == 0) { LOG_ERR("Expected new parent object to be specified via \"-C\"," " missing option."); result = false; } if (ctx.flags.c == 0) { LOG_ERR("Expected object to be specified via \"-c\"," " missing option."); result = false; } if (ctx.flags.s == 0) { LOG_ERR( "Expected encrypted seed out filename to be specified via \"-S\"," " missing option."); result = false; } if (ctx.flags.r == 0) { LOG_ERR("Expected private key out filename to be specified via \"-r\"," " missing option."); result = false; } } return result; } static bool set_key_algorithm(const char *algstr, TPMT_SYM_DEF_OBJECT * obj) { if (!strcmp(algstr, "null")) { obj->algorithm = TPM2_ALG_NULL; return true; } else if (!strcmp(algstr, "aes")) { obj->algorithm = TPM2_ALG_AES; obj->keyBits.aes = 128; obj->mode.aes = TPM2_ALG_CFB; return true; } LOG_ERR("The algorithm \"%s\" is not supported!", algstr); return false; } static tool_rc tpm2_create_duplicate( TPM2B_PUBLIC *parent_pub, TPM2B_SENSITIVE *privkey, TPM2B_PUBLIC *public, TPM2B_ENCRYPTED_SECRET *encrypted_seed) { bool result; tool_rc rc = tool_rc_success; TSS2_RC rval; /* * Calculate the object name. */ TPM2B_NAME pubname = TPM2B_TYPE_INIT(TPM2B_NAME, name); result = tpm2_identity_create_name(public, &pubname); if (!result) { return false; } TPM2B_DIGEST * seed = &privkey->sensitiveArea.seedValue; TPM2B_MAX_BUFFER hmac_key; TPM2B_MAX_BUFFER enc_key; tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key( parent_pub, &pubname, seed, &hmac_key, &enc_key); /* * Marshall the private key into a buffer */ TPM2B_MAX_BUFFER marshalled_sensitive = TPM2B_EMPTY_INIT; size_t marshalled_sensitive_size = 0; rval = Tss2_MU_TPMT_SENSITIVE_Marshal(&privkey->sensitiveArea, marshalled_sensitive.buffer + sizeof(marshalled_sensitive.size), TPM2_MAX_DIGEST_BUFFER, &marshalled_sensitive_size); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing sensitive area"); return false; } size_t marshalled_sensitive_size_info = 0; rval = Tss2_MU_UINT16_Marshal(marshalled_sensitive_size, marshalled_sensitive.buffer, sizeof(marshalled_sensitive.size), &marshalled_sensitive_size_info); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing sensitive area size"); return false; } marshalled_sensitive.size = marshalled_sensitive_size + marshalled_sensitive_size_info; /* * Compute the outer HMAC over the marshalled sensitive area * and encrypt it with the seed value. */ TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT; TPM2B_MAX_BUFFER encrypted_duplicate_sensitive = TPM2B_EMPTY_INIT; tpm2_identity_util_calculate_outer_integrity(parent_pub->publicArea.nameAlg, &pubname, &marshalled_sensitive, &hmac_key, &enc_key, &parent_pub->publicArea.parameters.rsaDetail.symmetric, &encrypted_duplicate_sensitive, &outer_hmac); /* * Build the private data structure for writing out */ TPM2B_PRIVATE private = TPM2B_EMPTY_INIT; UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_pub->publicArea.nameAlg); private.size = sizeof(parent_hash_size) + parent_hash_size + encrypted_duplicate_sensitive.size; size_t hmac_size_offset = 0; rval = Tss2_MU_UINT16_Marshal(parent_hash_size, private.buffer, sizeof(parent_hash_size), &hmac_size_offset); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing hmac size"); return false; } memcpy(private.buffer + hmac_size_offset, outer_hmac.buffer, parent_hash_size); memcpy(private.buffer + hmac_size_offset + parent_hash_size, encrypted_duplicate_sensitive.buffer, encrypted_duplicate_sensitive.size); /* * Write out the generated files */ result = files_save_encrypted_seed(encrypted_seed, ctx.enc_seed_out); if (!result) { LOG_ERR("Failed to save encryption seed into file \"%s\"", ctx.enc_seed_out); rc = tool_rc_general_error; goto out; } result = files_save_private(&private, ctx.duplicate_key_private_file); if (!result) { LOG_ERR("Failed to save private key into file \"%s\"", ctx.duplicate_key_private_file); rc = tool_rc_general_error; goto out; } result = files_save_public(public, ctx.duplicate_key_public_file); if (!result) { LOG_ERR("Failed to save public key into file \"%s\"", ctx.duplicate_key_public_file); rc = tool_rc_general_error; goto out; } out: return rc; } static void setup_default_attrs(TPMA_OBJECT *attrs, bool has_policy, bool has_auth) { /* Handle Default Setup */ *attrs = DEFAULT_DUPLICATE_ATTRS; /* * IMPORTANT: if the object we're creating has a policy and NO authvalue, turn off userwith auth * so empty passwords don't work on the object. */ if (has_policy && !has_auth) { *attrs &= ~TPMA_OBJECT_USERWITHAUTH; } } static tool_rc openssl_duplicate(void) { TPM2B_PUBLIC parent_public = TPM2B_EMPTY_INIT; TPM2B_PUBLIC public = TPM2B_EMPTY_INIT; TPM2B_SENSITIVE private = TPM2B_EMPTY_INIT; TPM2B_ENCRYPTED_SECRET encrypted_seed = TPM2B_EMPTY_INIT; bool result = files_load_public(ctx.parent_public_key_file, &parent_public); if (!result) return tool_rc_general_error; TPMA_OBJECT attrs = 0; setup_default_attrs(&attrs, !!ctx.duplicable_key.policy_str, !!ctx.duplicable_key.auth_str); TPM2B_PUBLIC template = { 0 }; tool_rc rc = tpm2_alg_util_public_init( ctx.key_type, NULL, /* name-alg: does this matter? */ NULL, /* DO attributes matter? */ ctx.duplicable_key.policy_str, attrs, &template); if (rc != tool_rc_success) { return rc; } result = tpm2_openssl_import_keys( &parent_public, &encrypted_seed, ctx.duplicable_key.auth_str, ctx.private_key_file, NULL, // passin &template, &private, &public ); if (!result) return tool_rc_general_error; return tpm2_create_duplicate(&parent_public, &private, &public, &encrypted_seed); } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tool_rc_general_error; TPMT_SYM_DEF_OBJECT sym_alg; TPM2B_DATA in_key; TPM2B_DATA* out_key = NULL; TPM2B_PRIVATE* duplicate; TPM2B_ENCRYPTED_SECRET* out_sym_seed; bool result = check_options(); if (!result) { return tool_rc_option_error; } if (ctx.flags.U) { return openssl_duplicate(); } rc = tpm2_util_object_load(ectx, ctx.new_parent_key.ctx_path, &ctx.new_parent_key.object, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } rc = tpm2_util_object_load_auth(ectx, ctx.duplicable_key.ctx_path, ctx.duplicable_key.auth_str, &ctx.duplicable_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid authorization"); return rc; } result = set_key_algorithm(ctx.key_type, &sym_alg); if (!result) { return tool_rc_general_error; } if (ctx.flags.i) { in_key.size = 16; result = files_load_bytes_from_path(ctx.sym_key_in, in_key.buffer, &in_key.size); if (!result) { return tool_rc_general_error; } if (in_key.size != 16) { LOG_ERR("Invalid AES key size, got %u bytes, expected 16", in_key.size); return tool_rc_general_error; } } rc = do_duplicate(ectx, ctx.flags.i ? &in_key : NULL, &sym_alg, ctx.flags.o ? &out_key : NULL, &duplicate, &out_sym_seed); if (rc != tool_rc_success || ctx.cp_hash_path) { return rc; } /* Maybe a false positive from scan-build but we'll check out_key anyway */ if (ctx.flags.o) { if (out_key == NULL) { LOG_ERR("No encryption key from TPM "); rc = tool_rc_general_error; goto out; } result = files_save_bytes_to_file(ctx.sym_key_out, out_key->buffer, out_key->size); if (!result) { LOG_ERR("Failed to save encryption key out into file \"%s\"", ctx.sym_key_out); rc = tool_rc_general_error; goto out; } } result = files_save_encrypted_seed(out_sym_seed, ctx.enc_seed_out); if (!result) { LOG_ERR("Failed to save encryption seed into file \"%s\"", ctx.enc_seed_out); rc = tool_rc_general_error; goto out; } result = files_save_private(duplicate, ctx.duplicate_key_private_file); if (!result) { LOG_ERR("Failed to save private key into file \"%s\"", ctx.duplicate_key_private_file); rc = tool_rc_general_error; goto out; } rc = tool_rc_success; out: free(out_key); free(out_sym_seed); free(duplicate); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.duplicable_key.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("duplicate", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_ecdhkeygen.c000066400000000000000000000054041412464516500177670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" typedef struct tpm_ecdhkeygen_ctx tpm_ecdhkeygen_ctx; struct tpm_ecdhkeygen_ctx { struct { const char *ctx_path; tpm2_loaded_object object; } ecc_public_key; const char *ecdh_pub_path; const char *ecdh_Z_path; TPM2B_ECC_POINT *Z; TPM2B_ECC_POINT *Q; }; static tpm_ecdhkeygen_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.ecc_public_key.ctx_path = value; break; case 'u': ctx.ecdh_pub_path = value; break; case 'o': ctx.ecdh_Z_path = value; break; }; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "context", required_argument, NULL, 'c' }, { "public", required_argument, NULL, 'u' }, { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("c:u:o:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc check_options(void) { if (!ctx.ecc_public_key.ctx_path) { LOG_ERR("Specify an ecc public key handle for context"); return tool_rc_option_error; } if (!ctx.ecdh_Z_path) { LOG_ERR("Specify path to save the ecdh secret or Z point"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_outputs(void) { bool result = files_save_ecc_point(ctx.Q, ctx.ecdh_pub_path); if (!result) { LOG_ERR("Failed to write out the public"); return tool_rc_general_error; } result = files_save_ecc_point(ctx.Z, ctx.ecdh_Z_path); if (!result) { LOG_ERR("Failed to write out the public"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // Process inputs rc = tpm2_util_object_load(ectx, ctx.ecc_public_key.ctx_path, &ctx.ecc_public_key.object, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { return rc; } // ESAPI call rc = tpm2_ecdhkeygen(ectx, &ctx.ecc_public_key.object, &ctx.Z, &ctx.Q); if (rc != tool_rc_success) { return rc; } // Process outputs rc = process_outputs(); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("ecdhkeygen", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_ecdhzgen.c000066400000000000000000000061531412464516500174520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" typedef struct tpm_ecdhzgen_ctx tpm_ecdhzgen_ctx; struct tpm_ecdhzgen_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } ecc_key; const char *ecdh_pub_path; const char *ecdh_Z_path; TPM2B_ECC_POINT *Z; TPM2B_ECC_POINT Q; }; static tpm_ecdhzgen_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.ecc_key.ctx_path = value; break; case 'p': ctx.ecc_key.auth_str = value; break; case 'u': ctx.ecdh_pub_path = value; break; case 'o': ctx.ecdh_Z_path = value; break; }; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "key-context", required_argument, NULL, 'c' }, { "key-auth", required_argument, NULL, 'p' }, { "public", required_argument, NULL, 'u' }, { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("c:p:u:o:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc check_options(void) { if (!ctx.ecc_key.ctx_path) { LOG_ERR("Specify an ecc public key handle for context"); return tool_rc_option_error; } if (!ctx.ecdh_Z_path) { LOG_ERR("Specify path to save the ecdh secret or Z point"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.ecc_key.ctx_path, ctx.ecc_key.auth_str, &ctx.ecc_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Failed to load object/ auth"); return rc; } bool result = true; result = files_load_ecc_point(ctx.ecdh_pub_path, &ctx.Q); if (!result) { LOG_ERR("Failed to load public input ECC point Q"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // Process inputs rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } // ESAPI call rc = tpm2_ecdhzgen(ectx, &ctx.ecc_key.object, &ctx.Z, &ctx.Q); if (rc != tool_rc_success) { return rc; } // Process outputs bool result = files_save_ecc_point(ctx.Z, ctx.ecdh_Z_path); if (!result) { LOG_ERR("Failed to write out the public"); return tool_rc_general_error; } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("ecdhzgen", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_ecephemeral.c000066400000000000000000000064471412464516500201430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_ecephemeral_ctx tpm_ecephemeral_ctx; struct tpm_ecephemeral_ctx { TPMI_ECC_CURVE curve_id; uint16_t counter; TPM2B_ECC_POINT *Q; char *commit_counter_path; char *ephemeral_pub_key_path; }; static tpm_ecephemeral_ctx ctx = { .curve_id = TPM2_ECC_NONE, }; static bool on_option(char key, char *value) { switch (key) { case 'u': ctx.ephemeral_pub_key_path = value; break; case 't': ctx.commit_counter_path = value; break; }; return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify a single argument for curveID"); return false; } bool result = true; TPM2B_PUBLIC algorithm = { 0 }; if (!tpm2_alg_util_handle_ext_alg(argv[0], &algorithm)) { result = false; } if (algorithm.publicArea.type != TPM2_ALG_ECC) { result = false; } if (algorithm.publicArea.parameters.eccDetail.curveID > TPM2_ECC_NIST_P521) { result = false; } if (!result) { LOG_ERR("Invalid/unsupported ECC curve: %s", argv[0]); return false; } ctx.curve_id = algorithm.publicArea.parameters.eccDetail.curveID; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "public", required_argument, NULL, 'u' }, { "counter", required_argument, NULL, 't' }, }; *opts = tpm2_options_new("u:t:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc check_options(void) { if (!ctx.ephemeral_pub_key_path) { LOG_ERR("Invalid path specified for saving the ephemeral public key"); return tool_rc_option_error; } if (!ctx.commit_counter_path) { LOG_ERR("Invalid path specified for saving the commit counter"); return tool_rc_option_error; } if (ctx.curve_id == TPM2_ECC_NONE) { LOG_ERR("Invalid/ unspecified ECC curve"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_outputs(void) { FILE *fp = fopen(ctx.commit_counter_path, "wb"); bool result = files_write_16(fp, ctx.counter); fclose(fp); if (!result) { LOG_ERR("Failed to write out the ECC commit count"); return tool_rc_general_error; } result = files_save_ecc_point(ctx.Q, ctx.ephemeral_pub_key_path); if (!result) { LOG_ERR("Failed to write out the ECC pub key"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // ESAPI call rc = tpm2_ecephemeral(ectx, ctx.curve_id, &ctx.Q, &ctx.counter); if (rc != tool_rc_success) { return rc; } // Process outputs rc = process_outputs(); Esys_Free(ctx.Q); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("ecephemeral", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_encryptdecrypt.c000066400000000000000000000270611412464516500207430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_options.h" #define MAX_INPUT_DATA_SIZE UINT16_MAX typedef struct tpm_encrypt_decrypt_ctx tpm_encrypt_decrypt_ctx; struct tpm_encrypt_decrypt_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } encryption_key; TPMI_YES_NO is_decrypt; uint8_t input_data[MAX_INPUT_DATA_SIZE]; uint16_t input_data_size; const char *input_path; char *out_file_path; uint8_t padded_block_len; bool is_padding_option_enabled; TPMI_ALG_SYM_MODE mode; struct { char *in; char *out; } iv; TPM2B_IV iv_start; char *cp_hash_path; }; static tpm_encrypt_decrypt_ctx ctx = { .mode = TPM2_ALG_NULL, .input_data_size = MAX_INPUT_DATA_SIZE, .padded_block_len = TPM2_MAX_SYM_BLOCK_SIZE, .is_padding_option_enabled = false, .iv_start = { .size = sizeof(ctx.iv_start.buffer), .buffer = { 0 } }, }; static tool_rc readpub(ESYS_CONTEXT *ectx, TPM2B_PUBLIC **public) { return tpm2_readpublic(ectx, ctx.encryption_key.object.tr_handle, public, NULL, NULL); } static bool evaluate_pkcs7_padding_requirements(uint16_t remaining_bytes, bool expected) { if (!ctx.is_padding_option_enabled) { return false; } if (ctx.is_decrypt != expected) { return false; } /* * If no ctx.mode was specified, the default cfb was set. */ if (ctx.mode != TPM2_ALG_CBC && ctx.mode != TPM2_ALG_ECB) { return false; } /* * Is last block? */ if (!(remaining_bytes <= TPM2_MAX_DIGEST_BUFFER && remaining_bytes > 0)) { return false; } LOG_WARN("Processing pkcs7 padding."); return true; } static void append_pkcs7_padding_data_to_input(uint8_t *pad_data, uint16_t *in_data_size, uint16_t *remaining_bytes) { bool test_pad_reqs = evaluate_pkcs7_padding_requirements(*remaining_bytes, false); if (!test_pad_reqs) { return; } *pad_data = ctx.padded_block_len - (*in_data_size % ctx.padded_block_len); memset(&ctx.input_data[ctx.input_data_size], *pad_data, *pad_data); if (*pad_data == ctx.padded_block_len) { *remaining_bytes += *pad_data; } if (*pad_data < ctx.padded_block_len) { *remaining_bytes = *in_data_size += *pad_data; } } static void strip_pkcs7_padding_data_from_output(uint8_t *pad_data, TPM2B_MAX_BUFFER *out_data, uint16_t *remaining_bytes) { bool test_pad_reqs = evaluate_pkcs7_padding_requirements(*remaining_bytes, true); if (!test_pad_reqs) { return; } uint8_t last_block_length = ctx.padded_block_len - (out_data->size % ctx.padded_block_len); if (last_block_length != ctx.padded_block_len) { LOG_WARN("Encrypted input is not block length aligned."); } *pad_data = out_data->buffer[last_block_length - 1]; out_data->size -= *pad_data; } static tool_rc encrypt_decrypt(ESYS_CONTEXT *ectx) { tool_rc rc = tool_rc_general_error; /* * try EncryptDecrypt2 first, and if the command is not supported by the TPM * fall back to EncryptDecrypt. */ UINT16 data_offset = 0; bool result = true; FILE *out_file_ptr = ctx.out_file_path ? fopen(ctx.out_file_path, "wb+") : stdout; if (!out_file_ptr) { LOG_ERR("Could not open file \"%s\", error: %s", ctx.out_file_path, strerror(errno)); return tool_rc_general_error; } TPM2B_MAX_BUFFER *out_data = NULL; TPM2B_MAX_BUFFER in_data; TPM2B_IV *iv_out = NULL; TPM2B_IV *iv_in = &ctx.iv_start; uint8_t pad_data = 0; uint16_t remaining_bytes = ctx.input_data_size; if (ctx.mode == TPM2_ALG_ECB) { iv_in = NULL; } if (ctx.cp_hash_path) { in_data.size = remaining_bytes; append_pkcs7_padding_data_to_input(&pad_data, &in_data.size, &remaining_bytes); memcpy(in_data.buffer, ctx.input_data, in_data.size); LOG_WARN("Calculating cpHash. Exiting without performing encryptdecrypt."); TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_encryptdecrypt(ectx, &ctx.encryption_key.object, ctx.is_decrypt, ctx.mode, iv_in, &in_data, &out_data, &iv_out, &cp_hash); if (rc != tool_rc_success) { LOG_ERR("CpHash calculation failed!"); fclose(out_file_ptr); return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } while (remaining_bytes > 0) { in_data.size = remaining_bytes > TPM2_MAX_DIGEST_BUFFER ? TPM2_MAX_DIGEST_BUFFER : remaining_bytes; if (!pad_data) { append_pkcs7_padding_data_to_input(&pad_data, &in_data.size, &remaining_bytes); } memcpy(in_data.buffer, &ctx.input_data[data_offset], in_data.size); rc = tpm2_encryptdecrypt(ectx, &ctx.encryption_key.object, ctx.is_decrypt, ctx.mode, iv_in, &in_data, &out_data, &iv_out, NULL); if (rc != tool_rc_success) { goto out; } /* * Copy iv_out iv_in to use it in next loop iteration. * This copy is also output from the tool for further chaining. */ if (ctx.mode != TPM2_ALG_ECB) { assert(iv_in); assert(iv_out); *iv_in = *iv_out; free(iv_out); } strip_pkcs7_padding_data_from_output(&pad_data, out_data, &remaining_bytes); result = files_write_bytes(out_file_ptr, out_data->buffer, out_data->size); free(out_data); if (!result) { LOG_ERR("Failed to save output data to file"); goto out; } remaining_bytes -= in_data.size; data_offset += in_data.size; } /* * iv_in here is the copy of final iv_out from the loop above. */ result = (ctx.iv.out && iv_in) ? files_save_bytes_to_file(ctx.iv.out, iv_in->buffer, iv_in->size) : true; if (!result) { goto out; } rc = tool_rc_success; out: if (out_file_ptr != stdout) { fclose(out_file_ptr); } return rc; } static void parse_iv(char *value) { ctx.iv.in = value; char *split = strchr(value, ':'); if (split) { *split = '\0'; split++; if (split) { ctx.iv.out = split; } } } static bool setup_alg_mode(ESYS_CONTEXT *ectx) { TPM2B_PUBLIC *public; tool_rc rc = readpub(ectx, &public); if (rc != tool_rc_success) { return false; } /* * Sym objects can have a NULL mode, which means the caller can and must determine mode. * Thus if the caller doesn't specify an algorithm, and the object has a default mode, choose it, * else choose CFB. * If the caller specifies an invalid mode, just pass it to the TPM and let it error out. */ if (ctx.mode == TPM2_ALG_NULL) { TPMI_ALG_SYM_MODE objmode = public->publicArea.parameters.symDetail.sym.mode.sym; if (objmode == TPM2_ALG_NULL) { ctx.mode = TPM2_ALG_CFB; } else { ctx.mode = objmode; } } free(public); return true; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.encryption_key.ctx_path = value; break; case 'p': ctx.encryption_key.auth_str = value; break; case 'd': ctx.is_decrypt = 1; break; case 'o': ctx.out_file_path = value; break; case 'G': ctx.mode = tpm2_alg_util_strtoalg(value, tpm2_alg_util_flags_mode); if (ctx.mode == TPM2_ALG_ERROR) { LOG_ERR("Invalid mode, got: %s", value); return false; } break; case 't': parse_iv(value); break; case 'e': ctx.is_padding_option_enabled = true; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool on_args(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Expected one input file, got: %d", argc); return false; } ctx.input_path = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "decrypt", no_argument, NULL, 'd' }, { "iv", required_argument, NULL, 't' }, { "mode", required_argument, NULL, 'G' }, { "output", required_argument, NULL, 'o' }, { "key-context", required_argument, NULL, 'c' }, { "pad", no_argument, NULL, 'e' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("p:edi:o:c:G:t:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static bool is_input_options_args_valid(void) { if (!ctx.encryption_key.ctx_path) { LOG_ERR("Expected a context file or handle, got none."); return false; } bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_path, &ctx.input_data_size, ctx.input_data); if (!result) { LOG_ERR("Failed to read in the input."); return result; } if (!ctx.iv.in) { LOG_WARN("Using a weak IV, try specifying an IV"); } if (ctx.iv.in) { unsigned long file_size; result = files_get_file_size_path(ctx.iv.in, &file_size); if (!result) { LOG_ERR("Could not retrieve iv file size."); return false; } if (file_size != ctx.iv_start.size) { LOG_ERR("Iv should be 16 bytes, got %lu", file_size); return false; } result = files_load_bytes_from_path(ctx.iv.in, ctx.iv_start.buffer, &ctx.iv_start.size); if (!result) { LOG_ERR("Could not load the iv from the file."); return false; } } if (ctx.cp_hash_path && ctx.input_data_size > TPM2_MAX_DIGEST_BUFFER) { LOG_ERR("Cannot calculate cpHash for buffer larger than max digest buffer."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_options_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.encryption_key.ctx_path, ctx.encryption_key.auth_str, &ctx.encryption_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid object key authorization"); return rc; } bool result = setup_alg_mode(ectx); if (!result) { LOG_ERR("Failure to setup key mode."); return tool_rc_general_error; } return encrypt_decrypt(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.encryption_key.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("encryptdecrypt", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_evictcontrol.c000066400000000000000000000137611412464516500204010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_capability.h" #include "tpm2_tool.h" typedef struct tpm_evictcontrol_ctx tpm_evictcontrol_ctx; struct tpm_evictcontrol_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; struct { char *ctx_path; tpm2_loaded_object object; } to_persist_key; TPMI_DH_PERSISTENT persist_handle; const char *output_arg; struct { UINT8 p :1; UINT8 c :1; UINT8 o :1; } flags; char *cp_hash_path; }; static tpm_evictcontrol_ctx ctx = { .auth_hierarchy.ctx_path="o", }; static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'c': ctx.to_persist_key.ctx_path = value; ctx.flags.c = 1; break; case 'o': ctx.output_arg = value; ctx.flags.o = 1; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool on_arg(int argc, char *argv[]) { if (argc > 1) { LOG_ERR("Expected at most one persistent handle, got %d", argc); return false; } const char *value = argv[0]; bool result = tpm2_util_string_to_uint32(value, &ctx.persist_handle); if (!result) { LOG_ERR("Could not convert persistent handle to a number, got: \"%s\"", value); return false; } ctx.flags.p = 1; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "object-context", required_argument, NULL, 'c' }, { "output", required_argument, NULL, 'o' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:c:o:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tool_rc_general_error; bool evicted = false; /* load up the object/handle to work on */ tool_rc tmp_rc = tpm2_util_object_load(ectx, ctx.to_persist_key.ctx_path, &ctx.to_persist_key.object, TPM2_HANDLE_ALL_W_NV); if (tmp_rc != tool_rc_success) { rc = tmp_rc; goto out; } /* load up the auth hierarchy */ tmp_rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (tmp_rc != tool_rc_success) { rc = tmp_rc; goto out; } if (ctx.to_persist_key.object.handle >> TPM2_HR_SHIFT == TPM2_HT_PERSISTENT) { ctx.persist_handle = ctx.to_persist_key.object.handle; ctx.flags.p = 1; } /* If we've been given a handle or context object to persist and not an * explicit persistent handle to use, find an available vacant handle in * the persistent namespace and use that. * * XXX: We need away to figure out of object is persistent and skip it. */ if (ctx.flags.c && !ctx.flags.p) { bool is_platform = ctx.auth_hierarchy.object.handle == TPM2_RH_PLATFORM; tmp_rc = tpm2_capability_find_vacant_persistent_handle(ectx, is_platform, &ctx.persist_handle); if (tmp_rc != tool_rc_success) { rc = tmp_rc; goto out; } /* we searched and found a persistent handle, so mark that peristent handle valid */ ctx.flags.p = 1; } if (ctx.flags.o && !ctx.flags.p) { LOG_ERR("Cannot specify -o without using a persistent handle"); goto out; } ESYS_TR out_tr; if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; LOG_WARN("Calculating cpHash. Exiting without evicting objects."); tool_rc rc = tpm2_evictcontrol(ectx, &ctx.auth_hierarchy.object, &ctx.to_persist_key.object, ctx.persist_handle, &out_tr, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } /* * ESAPI is smart enough that if the object is persistent, to ignore the argument * for persistent handle. Thus we can use ESYS_TR output to determine if it's * evicted or not. */ rc = tpm2_evictcontrol(ectx, &ctx.auth_hierarchy.object, &ctx.to_persist_key.object, ctx.persist_handle, &out_tr, NULL); if (rc != tool_rc_success) { goto out; } /* * Only Close a TR object if it's still resident in the TPM. * When these handles match, evictcontrol flushed it from the TPM. * It's evicted when ESAPI sends back a none handle on evictcontrol. * * XXX: This output is wrong because we can't determine what handle was * evicted on ESYS_TR input. * * See bug: https://github.com/tpm2-software/tpm2-tools/issues/1816 */ evicted = out_tr == ESYS_TR_NONE; tpm2_tool_output("persistent-handle: 0x%x\n", ctx.persist_handle); tpm2_tool_output("action: %s\n", evicted ? "evicted" : "persisted"); if (ctx.output_arg) { rc = files_save_ESYS_TR(ectx, out_tr, ctx.output_arg); } else { rc = tool_rc_success; } out: if (!evicted) { rc = tpm2_close(ectx, &out_tr); } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("evictcontrol", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_flushcontext.c000066400000000000000000000103401412464516500204020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_capability.h" #include "tpm2_options.h" struct tpm_flush_context_ctx { TPM2_HANDLE property; char *context_arg; unsigned encountered_option; }; static struct tpm_flush_context_ctx ctx; static const char *get_property_name(TPM2_HANDLE handle) { switch (handle & TPM2_HR_RANGE_MASK) { case TPM2_HR_TRANSIENT: return "transient"; case TPM2_HT_LOADED_SESSION << TPM2_HR_SHIFT: return "loaded session"; case TPM2_HT_SAVED_SESSION << TPM2_HR_SHIFT: return "saved session"; } return "invalid"; } static tool_rc flush_contexts_tpm2(ESYS_CONTEXT *ectx, TPM2_HANDLE handles[], UINT32 count) { UINT32 i; for (i = 0; i < count; ++i) { ESYS_TR handle; tool_rc rc = tpm2_util_sys_handle_to_esys_handle(ectx, handles[i], &handle); if (rc != tool_rc_success) { return rc; } rc = tpm2_flush_context(ectx, handle); if (rc != tool_rc_success) { LOG_ERR("Failed Flush Context for %s handle 0x%x", get_property_name(handles[i]), handles[i]); return rc; } } return tool_rc_success; } static bool flush_contexts_tr(ESYS_CONTEXT *ectx, ESYS_TR handles[], UINT32 count) { UINT32 i; for (i = 0; i < count; ++i) { tool_rc rc = tpm2_flush_context(ectx, handles[i]); if (rc != tool_rc_success) { return rc; } } return tool_rc_success; } static bool on_option(char key, char *value) { UNUSED(value); if (ctx.encountered_option) { LOG_ERR("Options -t, -l and -s are mutually exclusive"); return false; } ctx.encountered_option = true; switch (key) { case 't': ctx.property = TPM2_TRANSIENT_FIRST; break; case 'l': ctx.property = TPM2_LOADED_SESSION_FIRST; break; case 's': ctx.property = TPM2_ACTIVE_SESSION_FIRST; break; } return true; } static bool on_arg(int argc, char *argv[]) { if (ctx.encountered_option && argc != 0) { LOG_ERR("Options are mutually exclusive of an argument"); return false; } ctx.context_arg = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "transient-object", no_argument, NULL, 't' }, { "loaded-session", no_argument, NULL, 'l' }, { "saved-session", no_argument, NULL, 's' }, }; *opts = tpm2_options_new("tls", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (ctx.property) { TPMS_CAPABILITY_DATA *capability_data; tool_rc rc = tpm2_capability_get(ectx, TPM2_CAP_HANDLES, ctx.property, TPM2_MAX_CAP_HANDLES, &capability_data); if (rc != tool_rc_success) { return rc; } TPML_HANDLE *handles = &capability_data->data.handles; rc = flush_contexts_tpm2(ectx, handles->handle, handles->count); free(capability_data); return rc; } if (!ctx.context_arg) { LOG_ERR("Specify options to evict handles or a session context."); return tool_rc_option_error; } TPM2_HANDLE handle; bool result = tpm2_util_string_to_uint32(ctx.context_arg, &handle); if (!result) { /* hmm not a handle, try a session */ tpm2_session *s = NULL; tool_rc rc = tpm2_session_restore(ectx, ctx.context_arg, true, &s); if (rc != tool_rc_success) { return rc; } tpm2_session_close(&s); return tool_rc_success; } /* its a handle, call flush */ ESYS_TR tr_handle = ESYS_TR_NONE; tool_rc rc = tpm2_util_sys_handle_to_esys_handle(ectx, handle, &tr_handle); if (rc != tool_rc_success) { return rc; } return flush_contexts_tr(ectx, &tr_handle, 1); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("flushcontext", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_getcap.c000066400000000000000000000732061412464516500171310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "log.h" #include "pcr.h" #include "tpm2_alg_util.h" #include "tpm2_capability.h" #include "tpm2_cc_util.h" #include "tpm2_tool.h" /* * Older versions of tpm2-tss misspelled these constants' names. * See https://github.com/tpm2-software/tpm2-tss/issues/1500. */ #ifndef TPM2_PT_HR_TRANSIENT_MIN #define TPM2_PT_HR_TRANSIENT_MIN ((TPM2_PT) (TPM2_PT_FIXED + 14)) #define TPM2_PT_HR_PERSISTENT_MIN ((TPM2_PT) (TPM2_PT_FIXED + 15)) #define TPM2_PT_HR_NV_INDEX ((TPM2_PT) (TPM2_PT_VAR + 2)) #define TPM2_PT_HR_TRANSIENT_AVAIL ((TPM2_PT) (TPM2_PT_VAR + 7)) #define TPM2_PT_HR_PERSISTENT ((TPM2_PT) (TPM2_PT_VAR + 8)) #define TPM2_PT_HR_PERSISTENT_AVAIL ((TPM2_PT) (TPM2_PT_VAR + 9)) #endif /* convenience macro to convert flags into "1" / "0" strings */ #define prop_str(val) val ? "1" : "0" /* number of elements in the capability_map array */ #define CAPABILITY_MAP_COUNT \ (sizeof (capability_map) / sizeof (capability_map_entry_t)) /* Structure to map a string to the appropriate TPM2_CAP / TPM2_PT pair */ typedef struct capability_map_entry { char *capability_string; TPM2_CAP capability; UINT32 property; UINT32 count; } capability_map_entry_t; /* * Array of structures for use as a lookup table to map string representation * of a capability to the proper TPM2_CAP / TPM2_PT pair. */ capability_map_entry_t capability_map[] = { { .capability_string = "algorithms", .capability = TPM2_CAP_ALGS, .property = TPM2_ALG_FIRST, .count = TPM2_MAX_CAP_ALGS, }, { .capability_string = "commands", .capability = TPM2_CAP_COMMANDS, .property = TPM2_CC_FIRST, .count = TPM2_MAX_CAP_CC, }, { .capability_string = "pcrs", .capability = TPM2_CAP_PCRS, .property = 0, .count = TPM2_MAX_TPM_PROPERTIES, }, { .capability_string = "properties-fixed", .capability = TPM2_CAP_TPM_PROPERTIES, .property = TPM2_PT_FIXED, .count = TPM2_MAX_TPM_PROPERTIES, }, { .capability_string = "properties-variable", .capability = TPM2_CAP_TPM_PROPERTIES, .property = TPM2_PT_VAR, .count = TPM2_MAX_TPM_PROPERTIES, }, { .capability_string = "ecc-curves", .capability = TPM2_CAP_ECC_CURVES, .property = TPM2_ECC_NIST_P192, .count = TPM2_MAX_ECC_CURVES, }, { .capability_string = "handles-transient", .capability = TPM2_CAP_HANDLES, .property = TPM2_TRANSIENT_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-persistent", .capability = TPM2_CAP_HANDLES, .property = TPM2_PERSISTENT_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-permanent", .capability = TPM2_CAP_HANDLES, .property = TPM2_PERMANENT_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-pcr", .capability = TPM2_CAP_HANDLES, .property = TPM2_PCR_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-nv-index", .capability = TPM2_CAP_HANDLES, .property = TPM2_NV_INDEX_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-loaded-session", .capability = TPM2_CAP_HANDLES, .property = TPM2_LOADED_SESSION_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, { .capability_string = "handles-saved-session", .capability = TPM2_CAP_HANDLES, .property = TPM2_ACTIVE_SESSION_FIRST, .count = TPM2_MAX_CAP_HANDLES, }, }; /* * Structure to hold options for this tool. */ typedef struct capability_opts { char *capability_string; TPM2_CAP capability; UINT32 property; UINT32 count; bool list; } capability_opts_t; static capability_opts_t options; /* * This function uses the 'capability_string' field in the capabilities_opts * structure to locate the same string in the capability_map array and then * populates the 'capability' and 'property' fields of the capability_opts_t * structure with the appropriate values from the capability_map. * Return values: * true - the function executed normally. * false - no matching entry found in capability_map. */ bool sanity_check_capability_opts(void) { if (options.capability_string == NULL) { LOG_ERR("missing capability string, see --help"); return false; } size_t i; for (i = 0; i < CAPABILITY_MAP_COUNT; ++i) { int cmp = strcmp(capability_map[i].capability_string, options.capability_string); if (cmp == 0) { options.capability = capability_map[i].capability; options.property = capability_map[i].property; options.count = capability_map[i].count; return true; } } LOG_ERR("invalid capability string: %s, see --help", options.capability_string); return false; } static void print_cap_map() { size_t i; for (i = 0; i < CAPABILITY_MAP_COUNT; ++i) { const char *capstr = capability_map[i].capability_string; tpm2_tool_output("- %s\n", capstr); } } /* * There are a number of fixed TPM properties (tagged properties) that are * characters (8bit chars) packed into 32bit integers, trim leading and trailing spaces */ static char * get_uint32_as_chars(UINT32 value) { static char buf[5]; value = tpm2_util_ntoh_32(value); UINT8 *bytes = (UINT8 *) &value; /* * move the start of the string to the beginning * first non space character * Record the number of skips in i. */ unsigned i; for (i = 0; i < sizeof(value); i++) { UINT8 b = *bytes; if (!isspace(b)) { break; } bytes++; } /* record the number of trailing spaces in j */ unsigned j; for (j = sizeof(value) - i; j > i; j--) { UINT8 b = bytes[j - 1]; /* NULL bytes count as space */ if (b && !isspace(b)) { break; } } memcpy(buf, bytes, j); buf[j] = '\0'; return buf; } /* * Print string representations of the TPMA_MODES. */ static void tpm2_tool_output_tpma_modes(TPMA_MODES modes) { tpm2_tool_output("TPM2_PT_MODES:\n" " raw: 0x%X\n", modes); if (modes & TPMA_MODES_FIPS_140_2) tpm2_tool_output(" value: TPMA_MODES_FIPS_140_2\n"); if (modes & TPMA_MODES_RESERVED1_MASK) tpm2_tool_output( " value: TPMA_MODES_RESERVED1 (these bits shouldn't be set)\n"); } /* * Print string representation of the TPMA_PERMANENT attributes. */ static void dump_permanent_attrs(TPMA_PERMANENT attrs) { tpm2_tool_output("TPM2_PT_PERMANENT:\n"); tpm2_tool_output(" ownerAuthSet: %s\n", prop_str (attrs & TPMA_PERMANENT_OWNERAUTHSET)); tpm2_tool_output(" endorsementAuthSet: %s\n", prop_str (attrs & TPMA_PERMANENT_ENDORSEMENTAUTHSET)); tpm2_tool_output(" lockoutAuthSet: %s\n", prop_str (attrs & TPMA_PERMANENT_LOCKOUTAUTHSET)); tpm2_tool_output(" reserved1: %s\n", prop_str (attrs & TPMA_PERMANENT_RESERVED1_MASK)); tpm2_tool_output(" disableClear: %s\n", prop_str (attrs & TPMA_PERMANENT_DISABLECLEAR)); tpm2_tool_output(" inLockout: %s\n", prop_str (attrs & TPMA_PERMANENT_INLOCKOUT)); tpm2_tool_output(" tpmGeneratedEPS: %s\n", prop_str (attrs & TPMA_PERMANENT_TPMGENERATEDEPS)); tpm2_tool_output(" reserved2: %s\n", prop_str (attrs & TPMA_PERMANENT_RESERVED2_MASK)); } /* * Print string representations of the TPMA_STARTUP_CLEAR attributes. */ static void dump_startup_clear_attrs(TPMA_STARTUP_CLEAR attrs) { tpm2_tool_output("TPM2_PT_STARTUP_CLEAR:\n"); tpm2_tool_output(" phEnable: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_PHENABLE)); tpm2_tool_output(" shEnable: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_SHENABLE)); tpm2_tool_output(" ehEnable: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_EHENABLE));; tpm2_tool_output(" phEnableNV: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_PHENABLENV)); tpm2_tool_output(" reserved1: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_RESERVED1_MASK)); tpm2_tool_output(" orderly: %s\n", prop_str (attrs & TPMA_STARTUP_CLEAR_ORDERLY)); } /* * Iterate over all fixed properties, call the unique print function for each. */ static void dump_tpm_properties_fixed(TPMS_TAGGED_PROPERTY properties[], size_t count) { size_t i; char *buf; for (i = 0; i < count; ++i) { TPM2_PT property = properties[i].property; UINT32 value = properties[i].value; switch (property) { case TPM2_PT_FAMILY_INDICATOR: buf = get_uint32_as_chars(value); tpm2_tool_output("TPM2_PT_FAMILY_INDICATOR:\n" " raw: 0x%X\n" " value: \"%s\"\n", value, buf); break; case TPM2_PT_LEVEL: tpm2_tool_output("TPM2_PT_LEVEL:\n" " raw: %d\n", value); break; case TPM2_PT_REVISION: tpm2_tool_output("TPM2_PT_REVISION:\n" " raw: 0x%X\n" " value: %.2f\n", value, (float )value / 100); break; case TPM2_PT_DAY_OF_YEAR: tpm2_tool_output("TPM2_PT_DAY_OF_YEAR:\n" " raw: 0x%X\n", value); break; case TPM2_PT_YEAR: tpm2_tool_output("TPM2_PT_YEAR:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MANUFACTURER: { UINT32 he_value = tpm2_util_ntoh_32(value); tpm2_tool_output("TPM2_PT_MANUFACTURER:\n" " raw: 0x%X\n" " value: \"%.*s\"\n", value, (int )sizeof(value), (char * )&he_value); } break; case TPM2_PT_VENDOR_STRING_1: buf = get_uint32_as_chars(value); tpm2_tool_output("TPM2_PT_VENDOR_STRING_1:\n" " raw: 0x%X\n" " value: \"%s\"\n", value, buf); break; case TPM2_PT_VENDOR_STRING_2: buf = get_uint32_as_chars(value); tpm2_tool_output("TPM2_PT_VENDOR_STRING_2:\n" " raw: 0x%X\n" " value: \"%s\"\n", value, buf); break; case TPM2_PT_VENDOR_STRING_3: buf = get_uint32_as_chars(value); tpm2_tool_output("TPM2_PT_VENDOR_STRING_3:\n" " raw: 0x%X\n" " value: \"%s\"\n", value, buf); break; case TPM2_PT_VENDOR_STRING_4: buf = get_uint32_as_chars(value); tpm2_tool_output("TPM2_PT_VENDOR_STRING_4:\n" " raw: 0x%X\n" " value: \"%s\"\n", value, buf); break; case TPM2_PT_VENDOR_TPM_TYPE: tpm2_tool_output("TPM2_PT_VENDOR_TPM_TYPE:\n" " raw: 0x%X\n", value); break; case TPM2_PT_FIRMWARE_VERSION_1: tpm2_tool_output("TPM2_PT_FIRMWARE_VERSION_1:\n" " raw: 0x%X\n", value); break; case TPM2_PT_FIRMWARE_VERSION_2: tpm2_tool_output("TPM2_PT_FIRMWARE_VERSION_2:\n" " raw: 0x%X\n", value); break; case TPM2_PT_INPUT_BUFFER: tpm2_tool_output("TPM2_PT_INPUT_BUFFER:\n" " raw: 0x%X\n", value); break; case TPM2_PT_HR_TRANSIENT_MIN: tpm2_tool_output("TPM2_PT_HR_TRANSIENT_MIN:\n" " raw: 0x%X\n", value); break; case TPM2_PT_HR_PERSISTENT_MIN: tpm2_tool_output("TPM2_PT_HR_PERSISTENT_MIN:\n" " raw: 0x%X\n", value); break; case TPM2_PT_HR_LOADED_MIN: tpm2_tool_output("TPM2_PT_HR_LOADED_MIN:\n" " raw: 0x%X\n", value); break; case TPM2_PT_ACTIVE_SESSIONS_MAX: tpm2_tool_output("TPM2_PT_ACTIVE_SESSIONS_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PCR_COUNT: tpm2_tool_output("TPM2_PT_PCR_COUNT:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PCR_SELECT_MIN: tpm2_tool_output("TPM2_PT_PCR_SELECT_MIN:\n" " raw: 0x%X\n", value); break; case TPM2_PT_CONTEXT_GAP_MAX: tpm2_tool_output("TPM2_PT_CONTEXT_GAP_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_NV_COUNTERS_MAX: tpm2_tool_output("TPM2_PT_NV_COUNTERS_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_NV_INDEX_MAX: tpm2_tool_output("TPM2_PT_NV_INDEX_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MEMORY: tpm2_tool_output("TPM2_PT_MEMORY:\n" " raw: 0x%X\n", value); break; case TPM2_PT_CLOCK_UPDATE: tpm2_tool_output("TPM2_PT_CLOCK_UPDATE:\n" " raw: 0x%X\n", value); break; case TPM2_PT_CONTEXT_HASH: /* this may be a TPM2_ALG_ID type */ tpm2_tool_output("TPM2_PT_CONTEXT_HASH:\n" " raw: 0x%X\n", value); break; case TPM2_PT_CONTEXT_SYM: /* this is a TPM2_ALG_ID type */ tpm2_tool_output("TPM2_PT_CONTEXT_SYM:\n" " raw: 0x%X\n", value); break; case TPM2_PT_CONTEXT_SYM_SIZE: tpm2_tool_output("TPM2_PT_CONTEXT_SYM_SIZE:\n" " raw: 0x%X\n", value); break; case TPM2_PT_ORDERLY_COUNT: tpm2_tool_output("TPM2_PT_ORDERLY_COUNT:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MAX_COMMAND_SIZE: tpm2_tool_output("TPM2_PT_MAX_COMMAND_SIZE:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MAX_RESPONSE_SIZE: tpm2_tool_output("TPM2_PT_MAX_RESPONSE_SIZE:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MAX_DIGEST: tpm2_tool_output("TPM2_PT_MAX_DIGEST:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MAX_OBJECT_CONTEXT: tpm2_tool_output("TPM2_PT_MAX_OBJECT_CONTEXT:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MAX_SESSION_CONTEXT: tpm2_tool_output("TPM2_PT_MAX_SESSION_CONTEXT:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PS_FAMILY_INDICATOR: tpm2_tool_output("TPM2_PT_PS_FAMILY_INDICATOR:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PS_LEVEL: tpm2_tool_output("TPM2_PT_PS_LEVEL:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PS_REVISION: tpm2_tool_output("TPM2_PT_PS_REVISION:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PS_DAY_OF_YEAR: tpm2_tool_output("TPM2_PT_PS_DAY_OF_YEAR:\n" " raw: 0x%X\n", value); break; case TPM2_PT_PS_YEAR: tpm2_tool_output("TPM2_PT_PS_YEAR:\n" " raw: 0x%X\n", value); break; case TPM2_PT_SPLIT_MAX: tpm2_tool_output("TPM2_PT_SPLIT_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_TOTAL_COMMANDS: tpm2_tool_output("TPM2_PT_TOTAL_COMMANDS:\n" " raw: 0x%X\n", value); break; case TPM2_PT_LIBRARY_COMMANDS: tpm2_tool_output("TPM2_PT_LIBRARY_COMMANDS:\n" " raw: 0x%X\n", value); break; case TPM2_PT_VENDOR_COMMANDS: tpm2_tool_output("TPM2_PT_VENDOR_COMMANDS:\n" " raw: 0x%X\n", value); break; case TPM2_PT_NV_BUFFER_MAX: tpm2_tool_output("TPM2_PT_NV_BUFFER_MAX:\n" " raw: 0x%X\n", value); break; case TPM2_PT_MODES: tpm2_tool_output_tpma_modes((TPMA_MODES) value); break; } } } /* * Iterate over all variable properties, call the unique print function for each. */ static void dump_tpm_properties_var(TPMS_TAGGED_PROPERTY properties[], size_t count) { size_t i; for (i = 0; i < count; ++i) { TPM2_PT property = properties[i].property; UINT32 value = properties[i].value; switch (property) { case TPM2_PT_PERMANENT: dump_permanent_attrs((TPMA_PERMANENT) value); break; case TPM2_PT_STARTUP_CLEAR: dump_startup_clear_attrs((TPMA_STARTUP_CLEAR) value); break; case TPM2_PT_HR_NV_INDEX: tpm2_tool_output("TPM2_PT_HR_NV_INDEX: 0x%X\n", value); break; case TPM2_PT_HR_LOADED: tpm2_tool_output("TPM2_PT_HR_LOADED: 0x%X\n", value); break; case TPM2_PT_HR_LOADED_AVAIL: tpm2_tool_output("TPM2_PT_HR_LOADED_AVAIL: 0x%X\n", value); break; case TPM2_PT_HR_ACTIVE: tpm2_tool_output("TPM2_PT_HR_ACTIVE: 0x%X\n", value); break; case TPM2_PT_HR_ACTIVE_AVAIL: tpm2_tool_output("TPM2_PT_HR_ACTIVE_AVAIL: 0x%X\n", value); break; case TPM2_PT_HR_TRANSIENT_AVAIL: tpm2_tool_output("TPM2_PT_HR_TRANSIENT_AVAIL: 0x%X\n", value); break; case TPM2_PT_HR_PERSISTENT: tpm2_tool_output("TPM2_PT_HR_PERSISTENT: 0x%X\n", value); break; case TPM2_PT_HR_PERSISTENT_AVAIL: tpm2_tool_output("TPM2_PT_HR_PERSISTENT_AVAIL: 0x%X\n", value); break; case TPM2_PT_NV_COUNTERS: tpm2_tool_output("TPM2_PT_NV_COUNTERS: 0x%X\n", value); break; case TPM2_PT_NV_COUNTERS_AVAIL: tpm2_tool_output("TPM2_PT_NV_COUNTERS_AVAIL: 0x%X\n", value); break; case TPM2_PT_ALGORITHM_SET: tpm2_tool_output("TPM2_PT_ALGORITHM_SET: 0x%X\n", value); break; case TPM2_PT_LOADED_CURVES: tpm2_tool_output("TPM2_PT_LOADED_CURVES: 0x%X\n", value); break; case TPM2_PT_LOCKOUT_COUNTER: tpm2_tool_output("TPM2_PT_LOCKOUT_COUNTER: 0x%X\n", value); break; case TPM2_PT_MAX_AUTH_FAIL: tpm2_tool_output("TPM2_PT_MAX_AUTH_FAIL: 0x%X\n", value); break; case TPM2_PT_LOCKOUT_INTERVAL: tpm2_tool_output("TPM2_PT_LOCKOUT_INTERVAL: 0x%X\n", value); break; case TPM2_PT_LOCKOUT_RECOVERY: tpm2_tool_output("TPM2_PT_LOCKOUT_RECOVERY: 0x%X\n", value); break; case TPM2_PT_NV_WRITE_RECOVERY: tpm2_tool_output("TPM2_PT_NV_WRITE_RECOVERY: 0x%X\n", value); break; case TPM2_PT_AUDIT_COUNTER_0: tpm2_tool_output("TPM2_PT_AUDIT_COUNTER_0: 0x%X\n", value); break; case TPM2_PT_AUDIT_COUNTER_1: tpm2_tool_output("TPM2_PT_AUDIT_COUNTER_1: 0x%X\n", value); break; default: tpm2_tool_output("unknown%X: 0x%X\n", value, value); break; } } } /* * Print data about TPM2_ALG_ID in human readable form. */ static void dump_algorithm_properties(TPM2_ALG_ID id, TPMA_ALGORITHM alg_attrs) { const char *id_name = tpm2_alg_util_algtostr(id, tpm2_alg_util_flags_any); bool is_unknown = id_name == NULL; id_name = id_name ? id_name : "unknown"; if (!is_unknown) { tpm2_tool_output("%s:\n", id_name); } else { /* If it's unknown, we don't want N unknowns in the map, so * make them unknown42, unknown since that's unique. * We do it this way, as most folks will want to just look up * if a given alg via "friendly" name like rsa is supported. */ tpm2_tool_output("%s%x:\n", id_name, id); } tpm2_tool_output(" value: 0x%X\n", id); tpm2_tool_output(" asymmetric: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_ASYMMETRIC)); tpm2_tool_output(" symmetric: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_SYMMETRIC)); tpm2_tool_output(" hash: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_HASH)); tpm2_tool_output(" object: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_OBJECT)); tpm2_tool_output(" reserved: 0x%X\n", (alg_attrs & TPMA_ALGORITHM_RESERVED1_MASK) >> 4); tpm2_tool_output(" signing: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_SIGNING)); tpm2_tool_output(" encrypting: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_ENCRYPTING)); tpm2_tool_output(" method: %s\n", prop_str (alg_attrs & TPMA_ALGORITHM_METHOD)); } /* * Iterate over the count TPMS_ALG_PROPERTY entries and dump the * TPMA_ALGORITHM attributes for each. */ static void dump_algorithms(TPMS_ALG_PROPERTY alg_properties[], size_t count) { size_t i; for (i = 0; i < count; ++i) dump_algorithm_properties(alg_properties[i].alg, alg_properties[i].algProperties); } /* * Pretty print the bit fields from the TPMA_CC (UINT32) */ static bool dump_command_attrs(TPMA_CC tpma_cc) { const char *value = tpm2_cc_util_to_str( tpma_cc & TPMA_CC_COMMANDINDEX_MASK); /* not found, make a hex version of it */ if (!value) { /* * big enough for hex representation of * saturated U32 + 0x prefix and then some. */ static char _buf[16]; memset(_buf, 0, sizeof(_buf)); int rc = snprintf(_buf, sizeof(_buf), "0x%x", tpma_cc); /* ignore bytes, we don't care if it's truncated and it shouldnt happen */ UNUSED(rc); value = _buf; } tpm2_tool_output("%s:\n", value); tpm2_tool_output(" value: 0x%X\n", tpma_cc); tpm2_tool_output(" commandIndex: 0x%x\n", tpma_cc & TPMA_CC_COMMANDINDEX_MASK); tpm2_tool_output(" reserved1: 0x%x\n", (tpma_cc & TPMA_CC_RESERVED1_MASK) >> 16); tpm2_tool_output(" nv: %s\n", prop_str (tpma_cc & TPMA_CC_NV)); tpm2_tool_output(" extensive: %s\n", prop_str (tpma_cc & TPMA_CC_EXTENSIVE)); tpm2_tool_output(" flushed: %s\n", prop_str (tpma_cc & TPMA_CC_FLUSHED)); tpm2_tool_output(" cHandles: 0x%x\n", (tpma_cc & TPMA_CC_CHANDLES_MASK) >> TPMA_CC_CHANDLES_SHIFT); tpm2_tool_output(" rHandle: %s\n", prop_str (tpma_cc & TPMA_CC_RHANDLE)); tpm2_tool_output(" V: %s\n", prop_str (tpma_cc & TPMA_CC_V)); tpm2_tool_output(" Res: 0x%x\n", (tpma_cc & TPMA_CC_RES_MASK) >> TPMA_CC_RES_SHIFT); return true; } /* * Iterate over an array of TPM2_ECC_CURVEs and dump out a human readable * representation of each array member. */ static void dump_ecc_curves(TPM2_ECC_CURVE curve[], UINT32 count) { size_t i; for (i = 0; i < count; ++i) { switch (curve[i]) { case TPM2_ECC_NIST_P192: tpm2_tool_output("TPM2_ECC_NIST_P192: 0x%X\n", curve[i]); break; case TPM2_ECC_NIST_P224: tpm2_tool_output("TPM2_ECC_NIST_P224: 0x%X\n", curve[i]); break; case TPM2_ECC_NIST_P256: tpm2_tool_output("TPM2_ECC_NIST_P256: 0x%X\n", curve[i]); break; case TPM2_ECC_NIST_P384: tpm2_tool_output("TPM2_ECC_NIST_P384: 0x%X\n", curve[i]); break; case TPM2_ECC_NIST_P521: tpm2_tool_output("TPM2_ECC_NIST_P521: 0x%X\n", curve[i]); break; case TPM2_ECC_BN_P256: tpm2_tool_output("TPM2_ECC_BN_P256: 0x%X\n", curve[i]); break; case TPM2_ECC_BN_P638: tpm2_tool_output("TPM2_ECC_BN_P638: 0x%X\n", curve[i]); break; case TPM2_ECC_SM2_P256: tpm2_tool_output("TPM2_ECC_SM2_P256: 0x%X\n", curve[i]); break; default: tpm2_tool_output("unknown%X: 0x%X\n", curve[i], curve[i]); break; } } } /* * Iterate over an array of TPMA_CCs and dump out a human readable * representation of each array member. */ static bool dump_command_attr_array(TPMA_CC command_attributes[], UINT32 count) { size_t i; bool result = true; for (i = 0; i < count; ++i) result &= dump_command_attrs(command_attributes[i]); return result; } /* * Iterate over an array of TPML_HANDLEs and dump out the handle * values. */ static void dump_handles(TPM2_HANDLE handles[], UINT32 count) { UINT32 i; for (i = 0; i < count; ++i) tpm2_tool_output("- 0x%X\n", handles[i]); } /* * Query the TPM for TPM capabilities. */ static tool_rc get_tpm_capability_all(ESYS_CONTEXT *context, TPMS_CAPABILITY_DATA **capability_data) { return tpm2_capability_get(context, options.capability, options.property, options.count, capability_data); } /* * This function is a glorified switch statement. It uses the 'capability' * and 'property' fields from the capability_opts structure to find the right * print function for the capabilities in the 'capabilities' parameter. * On success it will return true, if it fails (is unable to find an * appropriate print function for the provided 'capability' / 'property' * pair or the print routine fails) then it will return false. */ static bool dump_tpm_capability(TPMU_CAPABILITIES *capabilities) { bool result = true; switch (options.capability) { case TPM2_CAP_ALGS: dump_algorithms(capabilities->algorithms.algProperties, capabilities->algorithms.count); break; case TPM2_CAP_COMMANDS: result = dump_command_attr_array( capabilities->command.commandAttributes, capabilities->command.count); break; case TPM2_CAP_TPM_PROPERTIES: switch (options.property) { case TPM2_PT_FIXED: dump_tpm_properties_fixed(capabilities->tpmProperties.tpmProperty, capabilities->tpmProperties.count); break; case TPM2_PT_VAR: dump_tpm_properties_var(capabilities->tpmProperties.tpmProperty, capabilities->tpmProperties.count); break; default: return false; } break; case TPM2_CAP_ECC_CURVES: dump_ecc_curves(capabilities->eccCurves.eccCurves, capabilities->eccCurves.count); break; case TPM2_CAP_HANDLES: switch (options.property & TPM2_HR_RANGE_MASK) { case TPM2_HR_TRANSIENT: case TPM2_HR_PERSISTENT: case TPM2_HR_PERMANENT: case TPM2_HR_PCR: case TPM2_HR_NV_INDEX: case TPM2_HT_LOADED_SESSION << TPM2_HR_SHIFT: case TPM2_HT_SAVED_SESSION << TPM2_HR_SHIFT: dump_handles(capabilities->handles.handle, capabilities->handles.count); break; default: return false; } break; case TPM2_CAP_PCRS: pcr_print_pcr_selections(&capabilities->assignedPCR); break; default: return false; } return result; } static bool on_option(char key, char *value) { UNUSED(value); switch (key) { case 'l': options.list = true; } return true; } static bool on_arg(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Only supports 1 capability group, got: %d", argc); return false; } options.capability_string = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "list", no_argument, NULL, 'l' }, }; *opts = tpm2_options_new("l", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); if (options.list && options.capability_string) { LOG_ERR("Cannot specify -l with a capability group."); return tool_rc_option_error; } /* list known capabilities, ie -l option */ if (options.list) { print_cap_map(); return tool_rc_success; } /* List a capability, ie option */ TPMS_CAPABILITY_DATA *capability_data = NULL; bool ret = sanity_check_capability_opts(); if (!ret) { return tool_rc_option_error; } /* get requested capability from TPM, dump it to stdout */ tool_rc rc = get_tpm_capability_all(context, &capability_data); if (rc != tool_rc_success) { return rc; } bool result = dump_tpm_capability(&capability_data->data); free(capability_data); return result ? tool_rc_success : tool_rc_general_error; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getcap", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_getcommandauditdigest.c000066400000000000000000000150241412464516500222250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_tool.h" typedef struct tpm_getcommandauditdigest_ctx tpm_getcommandauditdigest_ctx; struct tpm_getcommandauditdigest_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } key; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } endorsement_hierarchy; char *signature_path; char *message_path; tpm2_convert_sig_fmt sig_format; TPMI_ALG_HASH sig_hash_algorithm; TPM2B_DATA qualification_data; TPM2B_ATTEST *audit_info; TPMT_SIGNATURE *signature; TPMT_SIG_SCHEME in_scheme; }; static tpm_getcommandauditdigest_ctx ctx = { .sig_hash_algorithm = TPM2_ALG_NULL, .qualification_data = TPM2B_EMPTY_INIT, .endorsement_hierarchy = { .ctx_path = "e" }, .in_scheme = { .scheme = TPM2_ALG_NULL, } }; static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.endorsement_hierarchy.auth_str = value; break; case 'c': ctx.key.ctx_path = value; break; case 'p': ctx.key.auth_str = value; break; case 'q': ctx.qualification_data.size = sizeof(ctx.qualification_data.buffer); return tpm2_util_bin_from_hex_or_file(value, &ctx.qualification_data.size, ctx.qualification_data.buffer); break; case 's': ctx.signature_path = value; break; case 'm': ctx.message_path = value; break; case 'f': ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } break; case 'g': ctx.sig_hash_algorithm = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.sig_hash_algorithm == TPM2_ALG_ERROR) { LOG_ERR( "Could not convert signature hash algorithm selection, got: \"%s\"", value); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "hierarchy-auth", required_argument, NULL, 'P' }, { "key-context", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "qualification", required_argument, NULL, 'q' }, { "signature", required_argument, NULL, 's' }, { "message", required_argument, NULL, 'm' }, { "format", required_argument, NULL, 'f' }, { "hash-algorithm", required_argument, NULL, 'g' } }; *opts = tpm2_options_new("P:c:p:q:s:m:f:g:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool check_input_options_and_args(void) { if (!ctx.key.ctx_path) { LOG_ERR("Specify the signing key to use for signing attestation."); return false; } if (!ctx.signature_path) { LOG_ERR("Specify the file path to store the signature of the attestation data."); return false; } if (!ctx.message_path) { LOG_ERR("Specify the file path to store the attestation data."); return false; } return true; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * Load auths */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.endorsement_hierarchy.ctx_path, ctx.endorsement_hierarchy.auth_str, &ctx.endorsement_hierarchy.object, false, TPM2_HANDLE_FLAGS_E); if (rc != tool_rc_success) { LOG_ERR("Invalid endorsement hierarchy authorization"); return rc; } rc = tpm2_util_object_load_auth(ectx, ctx.key.ctx_path, ctx.key.auth_str, &ctx.key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } /* * Setup signature scheme */ rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.key.object.tr_handle, &ctx.sig_hash_algorithm, TPM2_ALG_NULL, &ctx.in_scheme); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc process_outputs(ESYS_CONTEXT *ectx) { UNUSED(ectx); bool result = true; if (ctx.signature_path) { result = tpm2_convert_sig_save(ctx.signature, ctx.sig_format, ctx.signature_path); } if (!result) { LOG_ERR("Failed to save the signature data."); return tool_rc_general_error; } if (ctx.message_path) { result = files_save_bytes_to_file(ctx.message_path, (UINT8*) ctx.audit_info->attestationData, ctx.audit_info->size); } if (!result) { LOG_ERR("Failed to save the attestation data."); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); //Check input arguments bool result = check_input_options_and_args(); if (!result) { return tool_rc_option_error; } //Process inputs tool_rc rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } //ESAPI call rc = tpm2_getcommandauditdigest(ectx, &ctx.endorsement_hierarchy.object, &ctx.key.object, &ctx.in_scheme, &ctx.qualification_data, &ctx.audit_info, &ctx.signature); if (rc != tool_rc_success) { return rc; } //Process Outputs rc = process_outputs(ectx); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tpm2_session_close(&ctx.key.object.session); if (rc != tool_rc_success) { LOG_ERR("Failed closing auth session for signing key handle."); } tool_rc tmp_rc = tpm2_session_close( &ctx.endorsement_hierarchy.object.session); if (rc != tool_rc_success) { LOG_ERR("Failed closing auth session for endorsement hierarchy handle."); return tmp_rc; } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getcommandauditdigest", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_geteccparameters.c000066400000000000000000000052651412464516500212040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_geteccparameters_ctx tpm_geteccparameters_ctx; struct tpm_geteccparameters_ctx { TPMI_ECC_CURVE curve_id; const char *ecc_parameters_path; }; static tpm_geteccparameters_ctx ctx = { .curve_id = TPM2_ECC_NONE, }; static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.ecc_parameters_path = value; break; }; return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify a single argument for curveID"); return false; } bool result = true; TPM2B_PUBLIC algorithm = { 0 }; if (!tpm2_alg_util_handle_ext_alg(argv[0], &algorithm)) { result = false; } if (algorithm.publicArea.type != TPM2_ALG_ECC) { result = false; } if (algorithm.publicArea.parameters.eccDetail.curveID > TPM2_ECC_NIST_P521) { result = false; } if (!result) { LOG_ERR("Invalid/unsupported ECC curve: %s", argv[0]); return false; } ctx.curve_id = algorithm.publicArea.parameters.eccDetail.curveID; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("o:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc check_options(void) { if (!ctx.ecc_parameters_path) { LOG_ERR("Invalid path specified for saving the ECC parameters."); return tool_rc_option_error; } if (ctx.curve_id == TPM2_ECC_NONE) { LOG_ERR("Invalid/ unspecified ECC curve"); return tool_rc_option_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); UNUSED(ectx); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // ESAPI call TPMS_ALGORITHM_DETAIL_ECC *parameters; rc = tpm2_geteccparameters(ectx, ctx.curve_id, ¶meters); if (rc != tool_rc_success) { return rc; } // Process outputs bool result = files_save_ecc_details(parameters, ctx.ecc_parameters_path); if (!result) { LOG_ERR("Failed to write out the ECC pub key"); return tool_rc_general_error; } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("geteccparameters", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_getekcertificate.c000066400000000000000000000565711412464516500211760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_auth_util.h" #include "tpm2_capability.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm_getekcertificate_ctx tpm_getekcertificate_ctx; struct tpm_getekcertificate_ctx { // TPM Device properties bool is_tpm2_device_active; bool is_cert_on_nv; bool is_intc_cert; bool is_rsa_ek_cert_nv_location_defined; bool is_ecc_ek_cert_nv_location_defined; bool is_tpmgeneratedeps; // Certficate data handling uint8_t cert_count; char *ec_cert_path_1; FILE *ec_cert_file_handle_1; char *ec_cert_path_2; FILE *ec_cert_file_handle_2; unsigned char *rsa_cert_buffer; uint16_t rsa_cert_buffer_size; unsigned char *ecc_cert_buffer; uint16_t ecc_cert_buffer_size; bool is_cert_raw; // EK certificate hosting particulars char *ek_server_addr; unsigned int SSL_NO_VERIFY; char *ek_path; bool verbose; TPM2B_PUBLIC *out_public; }; static tpm_getekcertificate_ctx ctx = { .is_tpm2_device_active = true, .ek_server_addr = "https://ekop.intel.com/ekcertservice/", .is_cert_on_nv = true, .cert_count = 0, }; static unsigned char *hash_ek_public(void) { unsigned char *hash = (unsigned char*) malloc(SHA256_DIGEST_LENGTH); if (!hash) { LOG_ERR("OOM"); return NULL; } EVP_MD_CTX *sha256 = EVP_MD_CTX_new(); int is_success = EVP_DigestInit(sha256, EVP_sha256()); if (!is_success) { LOG_ERR("EVP_DigestInit failed"); goto err; } switch (ctx.out_public->publicArea.type) { case TPM2_ALG_RSA: is_success = EVP_DigestUpdate(sha256, ctx.out_public->publicArea.unique.rsa.buffer, ctx.out_public->publicArea.unique.rsa.size); if (!is_success) { LOG_ERR("EVP_DigestUpdate failed"); goto err; } if (ctx.out_public->publicArea.parameters.rsaDetail.exponent != 0) { LOG_ERR("non-default exponents unsupported"); goto err; } BYTE buf[3] = { 0x1, 0x00, 0x01 }; // Exponent is_success = EVP_DigestUpdate(sha256, buf, sizeof(buf)); if (!is_success) { LOG_ERR("EVP_DigestUpdate failed"); goto err; } break; case TPM2_ALG_ECC: is_success = EVP_DigestUpdate(sha256, ctx.out_public->publicArea.unique.ecc.x.buffer, ctx.out_public->publicArea.unique.ecc.x.size); if (!is_success) { LOG_ERR("EVP_DigestUpdate failed"); goto err; } is_success = EVP_DigestUpdate(sha256, ctx.out_public->publicArea.unique.ecc.y.buffer, ctx.out_public->publicArea.unique.ecc.y.size); if (!is_success) { LOG_ERR("EVP_DigestUpdate failed"); goto err; } break; default: LOG_ERR("unsupported EK algorithm"); goto err; } is_success = EVP_DigestFinal_ex(sha256, hash, NULL); if (!is_success) { LOG_ERR("EVP_DigestFinal failed"); goto err; } EVP_MD_CTX_free(sha256); if (ctx.verbose) { tpm2_tool_output("public-key-hash:\n"); tpm2_tool_output(" sha256: "); unsigned i; for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { tpm2_tool_output("%02X", hash[i]); } tpm2_tool_output("\n"); } return hash; err: free(hash); EVP_MD_CTX_free(sha256); return NULL; } static char *base64_encode(const unsigned char* buffer) { BIO *bio, *b64; BUF_MEM *buffer_pointer; LOG_INFO("Calculating the base64_encode of the hash of the Endorsement" "Public Key:"); if (buffer == NULL) { LOG_ERR("hash_ek_public returned null"); return NULL; } b64 = BIO_new(BIO_f_base64()); bio = BIO_new(BIO_s_mem()); bio = BIO_push(b64, bio); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); BIO_write(bio, buffer, SHA256_DIGEST_LENGTH); UNUSED(BIO_flush(bio)); BIO_get_mem_ptr(bio, &buffer_pointer); /* these are not NULL terminated */ char *b64text = buffer_pointer->data; size_t len = buffer_pointer->length; size_t i; for (i = 0; i < len; i++) { if (b64text[i] == '+') { b64text[i] = '-'; } if (b64text[i] == '/') { b64text[i] = '_'; } } char *final_string = NULL; CURL *curl = curl_easy_init(); if (curl) { char *output = curl_easy_escape(curl, b64text, len); if (output) { final_string = strdup(output); curl_free(output); } } curl_easy_cleanup(curl); curl_global_cleanup(); BIO_free_all(bio); /* format to a proper NULL terminated string */ return final_string; } static size_t writecallback(char *contents, size_t size, size_t nitems, void *CERT_BUFFER) { strncpy(CERT_BUFFER, (const char *)contents, nitems * size); ctx.rsa_cert_buffer_size = nitems * size; return ctx.rsa_cert_buffer_size; } static bool retrieve_web_endorsement_certificate(char *b64h) { #define NULL_TERM_LEN 1 // '\0' #define PATH_JOIN_CHAR_LEN 1 // '/' size_t len = strlen(ctx.ek_server_addr) + strlen(b64h) + NULL_TERM_LEN + PATH_JOIN_CHAR_LEN; char *weblink = (char *) malloc(len); if (!weblink) { LOG_ERR("oom"); return false; } bool ret = true; CURLcode rc = curl_global_init(CURL_GLOBAL_DEFAULT); if (rc != CURLE_OK) { LOG_ERR("curl_global_init failed: %s", curl_easy_strerror(rc)); ret = false; goto out_memory; } CURL *curl = curl_easy_init(); if (!curl) { LOG_ERR("curl_easy_init failed"); ret = false; goto out_global_cleanup; } /* * should not be used - Used only on platforms with older CA certificates. */ if (ctx.SSL_NO_VERIFY) { rc = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_SSL_VERIFYPEER failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } } snprintf(weblink, len, "%s%s%s", ctx.ek_server_addr, "/", b64h); rc = curl_easy_setopt(curl, CURLOPT_URL, weblink); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_URL failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } /* * If verbose is set, add in diagnostic information for debugging connections. * https://curl.haxx.se/libcurl/c/CURLOPT_VERBOSE.html */ rc = curl_easy_setopt(curl, CURLOPT_VERBOSE, (long )ctx.verbose); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_VERBOSE failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } rc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecallback); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_WRITEFUNCTION failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } /* * As only one cert is downloaded at a time, we can simply use * rsa_cert_buffer for either RSA EK cert or ECC EK cert. */ ctx.rsa_cert_buffer = malloc(CURL_MAX_WRITE_SIZE); rc = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)ctx.rsa_cert_buffer); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_WRITEDATA failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } rc = curl_easy_setopt(curl, CURLOPT_FAILONERROR, true); if (rc != CURLE_OK) { LOG_ERR("curl_easy_setopt for CURLOPT_FAILONERROR failed: %s", curl_easy_strerror(rc)); goto out_easy_cleanup; } rc = curl_easy_perform(curl); if (rc != CURLE_OK) { LOG_ERR("curl_easy_perform() failed: %s", curl_easy_strerror(rc)); ret = false; goto out_easy_cleanup; } out_easy_cleanup: curl_easy_cleanup(curl); out_global_cleanup: curl_global_cleanup(); out_memory: free(weblink); return ret; } static bool get_web_ek_certificate(void) { if (ctx.SSL_NO_VERIFY) { LOG_WARN("TLS communication with the said TPM manufacturer server setup" " with SSL_NO_VERIFY!"); } bool ret = true; unsigned char *hash = hash_ek_public(); char *b64 = base64_encode(hash); if (!b64) { LOG_ERR("base64_encode returned null"); ret = false; goto out; } LOG_INFO("%s", b64); ret = retrieve_web_endorsement_certificate(b64); free(b64); out: free(hash); return ret; } #define INTC 0x494E5443 #define IBM 0x49424D20 #define RSA_EK_CERT_NV_INDEX 0x01C00002 #define ECC_EK_CERT_NV_INDEX 0x01C0000A tool_rc get_tpm_properties(ESYS_CONTEXT *ectx) { TPMI_YES_NO more_data; TPMS_CAPABILITY_DATA *capability_data; tool_rc rc = tool_rc_success; rc = tpm2_getcap(ectx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_MANUFACTURER, 1, &more_data, &capability_data); if (rc != tool_rc_success) { LOG_ERR("TPM property read failure."); goto get_tpm_properties_out; } if (capability_data->data.tpmProperties.tpmProperty[0].value == IBM) { LOG_WARN("The TPM device is a simulator —— Inspect the certficate chain and root certificate"); } if (capability_data->data.tpmProperties.tpmProperty[0].value == INTC) { ctx.is_intc_cert = true; } free(capability_data); rc = tpm2_getcap(ectx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_PERMANENT, 1, &more_data, &capability_data); if (rc != tool_rc_success) { LOG_ERR("TPM property read failure."); goto get_tpm_properties_out; } if (capability_data->data.tpmProperties.tpmProperty[0].value & TPMA_PERMANENT_TPMGENERATEDEPS) { ctx.is_tpmgeneratedeps = true; } free(capability_data); rc = tpm2_getcap(ectx, TPM2_CAP_HANDLES, tpm2_util_hton_32(TPM2_HT_NV_INDEX), TPM2_PT_NV_INDEX_MAX, NULL, &capability_data); if (rc != tool_rc_success) { LOG_ERR("Failed to read capability data for NV indices."); ctx.is_cert_on_nv = false; goto get_tpm_properties_out; } if (capability_data->data.handles.count == 0) { ctx.is_cert_on_nv = false; goto get_tpm_properties_out; } UINT32 i; for (i = 0; i < capability_data->data.handles.count; i++) { TPMI_RH_NV_INDEX index = capability_data->data.handles.handle[i]; if (index == RSA_EK_CERT_NV_INDEX) { ctx.is_rsa_ek_cert_nv_location_defined = true; } if (index == ECC_EK_CERT_NV_INDEX) { ctx.is_ecc_ek_cert_nv_location_defined = true; } } if (!ctx.is_rsa_ek_cert_nv_location_defined && !ctx.is_ecc_ek_cert_nv_location_defined) { ctx.is_cert_on_nv = false; } get_tpm_properties_out: free(capability_data); return rc; } static tool_rc nv_read(ESYS_CONTEXT *ectx, TPMI_RH_NV_INDEX nv_index) { /* * Typical NV Index holding EK certificate has an empty auth * with attributes: * ppwrite|ppread|ownerread|authread|no_da|written|platformcreate */ char index_string[11]; if (nv_index == RSA_EK_CERT_NV_INDEX) { strcpy(index_string, "0x01C00002"); } else { strcpy(index_string, "0x01C0000A"); } tpm2_loaded_object object; tool_rc tmp_rc = tool_rc_success; tool_rc rc = tpm2_util_object_load_auth(ectx, index_string, NULL, &object, false, TPM2_HANDLE_FLAGS_NV); if (rc != tool_rc_success) { goto nv_read_out; } TPM2B_DIGEST cp_hash = { 0 }; TPM2B_DIGEST rp_hash = { 0 }; rc = nv_index == RSA_EK_CERT_NV_INDEX ? tpm2_util_nv_read(ectx, nv_index, 0, 0, &object, &ctx.rsa_cert_buffer, &ctx.rsa_cert_buffer_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0, ESYS_TR_NONE, ESYS_TR_NONE) : tpm2_util_nv_read(ectx, nv_index, 0, 0, &object, &ctx.ecc_cert_buffer, &ctx.ecc_cert_buffer_size, &cp_hash, &rp_hash, TPM2_ALG_SHA256, 0, ESYS_TR_NONE, ESYS_TR_NONE); nv_read_out: tmp_rc = tpm2_session_close(&object.session); if (rc != tool_rc_success) { return tmp_rc; } return rc; } static tool_rc get_nv_ek_certificate(ESYS_CONTEXT *ectx) { if (!ctx.is_cert_on_nv) { LOG_ERR("TCG specified location for EK certs aren't defined."); return tool_rc_general_error; } if (ctx.SSL_NO_VERIFY) { LOG_WARN("Ignoring -X or --allow-unverified if EK certificate found on NV"); } if (ctx.ek_path) { LOG_WARN("Ignoring -u or --ek-public option if EK certificate found on NV"); return tool_rc_option_error; } if (ctx.is_rsa_ek_cert_nv_location_defined && ctx.is_ecc_ek_cert_nv_location_defined && ctx.cert_count == 1) { LOG_WARN("Found 2 certficates on NV. Add another -o to save the ECC cert"); } if ((!ctx.is_rsa_ek_cert_nv_location_defined || !ctx.is_ecc_ek_cert_nv_location_defined) && ctx.cert_count == 2) { LOG_WARN("Ignoring the additional output file since only 1 cert found on NV"); } tool_rc rc = tool_rc_success; if (ctx.is_rsa_ek_cert_nv_location_defined) { rc = nv_read(ectx, RSA_EK_CERT_NV_INDEX); if (rc != tool_rc_success) { return rc; } } if (ctx.is_ecc_ek_cert_nv_location_defined) { rc = nv_read(ectx, ECC_EK_CERT_NV_INDEX); } return rc; } static tool_rc print_intel_ek_certificate_warning(void) { if (ctx.is_intc_cert && ctx.is_tpmgeneratedeps && !ctx.is_cert_on_nv) { LOG_ERR("Cannot proceed. For further information please refer to: " "https://www.intel.com/content/www/us/en/security-center/" "advisory/intel-sa-00086.html. Recovery tools are located here:" "https://github.com/intel/INTEL-SA-00086-Linux-Recovery-Tools"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc get_ek_certificates(ESYS_CONTEXT *ectx) { tool_rc rc = tool_rc_success; if (ctx.is_cert_on_nv) { rc = get_nv_ek_certificate(ectx); if (rc == tool_rc_success) { return rc; } else { LOG_WARN("EK certificate not found on NV"); ctx.is_cert_on_nv = false; } } /* * Following is everything applicable to ctx.is_cert_on_nv = false. */ rc = print_intel_ek_certificate_warning(); if (rc != tool_rc_success) { return rc; } if (!ctx.ek_path) { LOG_ERR("Must specify the EK public key path"); return tool_rc_option_error; } if (ctx.cert_count > 1) { LOG_ERR("Specify one output path for EK cert file per EK public key"); return tool_rc_option_error; } bool retval = get_web_ek_certificate(); if (!retval) { return tool_rc_general_error; } return tool_rc_success; } static tool_rc process_input(ESYS_CONTEXT *ectx) { if (ctx.ek_path) { ctx.out_public = malloc(sizeof(*ctx.out_public)); ctx.out_public->size = 0; bool res = files_load_public(ctx.ek_path, ctx.out_public); if (!res) { LOG_ERR("Could not load EK public from file"); return tool_rc_general_error; } } tool_rc rc = tool_rc_success; if (ctx.is_tpm2_device_active) { rc = get_tpm_properties(ectx); if (rc != tool_rc_success) { return rc; } } return print_intel_ek_certificate_warning(); } static char *base64_decode(char **split, unsigned int cert_length) { *split += strlen("certficate\" : "); char *final_string = NULL; int outlen; CURL *curl = curl_easy_init(); if (curl) { char *output = curl_easy_unescape(curl, *split, cert_length, &outlen); if (output) { final_string = strdup(output); curl_free(output); } } curl_easy_cleanup(curl); curl_global_cleanup(); if(final_string) { size_t i; for (i = 0; i < strlen(final_string); i++) { final_string[i] = final_string[i] == '-' ? '+' : final_string[i]; final_string[i] = final_string[i] == '_' ? '/' : final_string[i]; final_string[i] = final_string[i] == '"' ? '\0' : final_string[i]; final_string[i] = final_string[i] == '}' ? '\0' : final_string[i]; } } return final_string; } #define PEM_BEGIN_CERT_LINE "\n-----BEGIN CERTIFICATE-----\n" #define PEM_END_CERT_LINE "\n-----END CERTIFICATE-----\n" static tool_rc process_output(void) { /* * Check if the cert is from INTC based on certificated data containing * the EK public hash in addition to the certificate data. * If so set the flag. */ if (ctx.rsa_cert_buffer) { ctx.is_intc_cert = ctx.is_intc_cert ? ctx.is_intc_cert : !(strncmp((const char *)ctx.rsa_cert_buffer, "{\"pubhash", strlen("{\"pubhash"))); } if (ctx.ecc_cert_buffer) { ctx.is_intc_cert = ctx.is_intc_cert ? ctx.is_intc_cert : !(strncmp((const char *)ctx.ecc_cert_buffer, "{\"pubhash", strlen("{\"pubhash"))); } /* * Intel EK certificates on the NV-index are already in standard DER format. */ if (ctx.is_intc_cert && ctx.is_cert_on_nv) { ctx.is_cert_raw = true; } /* * Convert Intel EK certificates as received in the URL safe variant of * Base 64: https://tools.ietf.org/html/rfc4648#section-5 to PEM */ if (ctx.rsa_cert_buffer && ctx.is_intc_cert && !ctx.is_cert_raw) { char *split = strstr((const char *)ctx.rsa_cert_buffer, "certificate"); char *copy_buffer = base64_decode(&split, ctx.rsa_cert_buffer_size); ctx.rsa_cert_buffer_size = strlen(PEM_BEGIN_CERT_LINE) + strlen(copy_buffer) + strlen(PEM_END_CERT_LINE); strcpy((char *)ctx.rsa_cert_buffer, PEM_BEGIN_CERT_LINE); strcpy((char *)ctx.rsa_cert_buffer + strlen(PEM_BEGIN_CERT_LINE), copy_buffer); strcpy((char *)ctx.rsa_cert_buffer + strlen(PEM_BEGIN_CERT_LINE) + strlen(copy_buffer), PEM_END_CERT_LINE); free(copy_buffer); } if (ctx.ecc_cert_buffer && ctx.is_intc_cert && !ctx.is_cert_raw) { char *split = strstr((const char *)ctx.ecc_cert_buffer, "certificate"); char *copy_buffer = base64_decode(&split, ctx.ecc_cert_buffer_size); ctx.ecc_cert_buffer_size = strlen(PEM_BEGIN_CERT_LINE) + strlen(copy_buffer) + strlen(PEM_END_CERT_LINE); strcpy((char *)ctx.ecc_cert_buffer, PEM_BEGIN_CERT_LINE); strcpy((char *)ctx.ecc_cert_buffer + strlen(PEM_BEGIN_CERT_LINE), copy_buffer); strcpy((char *)ctx.ecc_cert_buffer + strlen(PEM_BEGIN_CERT_LINE) + strlen(copy_buffer), PEM_END_CERT_LINE); free(copy_buffer); } bool retval = true; if (ctx.rsa_cert_buffer) { retval = files_write_bytes( ctx.ec_cert_file_handle_1 ? ctx.ec_cert_file_handle_1 : stdout, ctx.rsa_cert_buffer, ctx.rsa_cert_buffer_size); if (!retval) { return tool_rc_general_error; } } if (ctx.ecc_cert_buffer) { retval = files_write_bytes( ctx.ec_cert_file_handle_2 ? ctx.ec_cert_file_handle_2 : ctx.rsa_cert_buffer ? stdout : ctx.ec_cert_file_handle_1, ctx.ecc_cert_buffer, ctx.ecc_cert_buffer_size); if (!retval) { return tool_rc_general_error; } } return tool_rc_success; } static tool_rc check_input_options(void) { if (!ctx.ek_path && !ctx.is_cert_on_nv) { LOG_ERR("Must specify the EK public key path"); return tool_rc_option_error; } if (!ctx.ek_server_addr && !ctx.is_cert_on_nv) { LOG_ERR("Must specify a valid remote server url!"); return tool_rc_option_error; } if (ctx.ec_cert_path_1) { ctx.ec_cert_file_handle_1 = fopen(ctx.ec_cert_path_1, "wb"); if (!ctx.ec_cert_file_handle_1) { LOG_ERR("Could not open file for writing: \"%s\"", ctx.ec_cert_path_1); return tool_rc_general_error; } } if (ctx.ec_cert_path_2) { ctx.ec_cert_file_handle_2 = fopen(ctx.ec_cert_path_2, "wb"); if (!ctx.ec_cert_file_handle_2) { LOG_ERR("Could not open file for writing: \"%s\"", ctx.ec_cert_path_2); return tool_rc_general_error; } } return tool_rc_success; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Only supports one remote server url, got: %d", argc); return false; } ctx.ek_server_addr = argv[0]; ctx.is_cert_on_nv = false; return true; } static bool on_option(char key, char *value) { switch (key) { case 'o': if (ctx.cert_count < 2) { ctx.cert_count++; } else { LOG_ERR("Specify only 2 outputs for RSA/ ECC certificates"); return false; } if (ctx.cert_count == 1) { ctx.ec_cert_path_1 = value; } if (ctx.cert_count == 2) { ctx.ec_cert_path_2 = value; } break; case 'X': ctx.SSL_NO_VERIFY = 1; break; case 'u': ctx.ek_path = value; break; case 'x': ctx.is_tpm2_device_active = false; ctx.is_cert_on_nv = false; break; case 0: ctx.is_cert_raw = true; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "ek-certificate", required_argument, NULL, 'o' }, { "allow-unverified", no_argument, NULL, 'X' }, { "ek-public", required_argument, NULL, 'u' }, { "offline", no_argument, NULL, 'x' }, { "raw", no_argument, NULL, 0 }, }; *opts = tpm2_options_new("o:u:Xx", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(ectx); tool_rc rc = check_input_options(); if (rc != tool_rc_success) { return rc; } rc = process_input(ectx); if (rc != tool_rc_success) { return rc; } ctx.verbose = flags.verbose; rc = get_ek_certificates(ectx); if (rc != tool_rc_success) { return rc; } return process_output(); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (ctx.ec_cert_file_handle_1) { fclose(ctx.ec_cert_file_handle_1); } if (ctx.ec_cert_file_handle_2) { fclose(ctx.ec_cert_file_handle_2); } if (ctx.rsa_cert_buffer) { free(ctx.rsa_cert_buffer); } if (ctx.ecc_cert_buffer) { free(ctx.ecc_cert_buffer); } return tool_rc_success; } static void tpm2_tool_onexit(void) { if (ctx.out_public) { free(ctx.out_public); } } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getekcertificate", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_getpolicydigest.c000066400000000000000000000121001412464516500210470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct tpm_getpolicydigest_ctx tpm_getpolicydigest_ctx; struct tpm_getpolicydigest_ctx { /* * Input options */ bool hex; /* * Outputs */ const char *output_file; TPM2B_DIGEST *policy_digest; /* * Parameter hashes */ /* * Aux Sessions */ tpm2_session *session; const char *session_path; ESYS_TR session_handle; }; static tpm_getpolicydigest_ctx ctx; static tool_rc get_policydigest(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ tool_rc rc = tpm2_policy_getdigest(ectx, ctx.session_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &ctx.policy_digest); if (rc != tool_rc_success) { LOG_ERR("Failed getrandom"); } return rc; } static tool_rc process_outputs(void) { /* * 1. Outputs that do not require TPM2_CC_ dispatch */ /* * 2. Outputs generated after TPM2_CC_ dispatch */ /* * Either open an output file, or if stdout, do nothing as -Q * was specified. */ tool_rc rc = tool_rc_success; FILE *out = stdout; if (ctx.output_file) { out = fopen(ctx.output_file, "wb+"); if (!out) { LOG_ERR("Could not open output file \"%s\", error: %s", ctx.output_file, strerror(errno)); rc = tool_rc_general_error; goto out; } } else if (!output_enabled) { goto out; } if (ctx.hex) { tpm2_util_print_tpm2b2(out, ctx.policy_digest); goto out; } bool is_file_op_success = files_write_bytes(out, ctx.policy_digest->buffer, ctx.policy_digest->size); if (!is_file_op_success) { rc = tool_rc_general_error; } out: if (out && out != stdout) { fclose(out); } return rc; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions * Note: Old-auth value is ignored when calculating cpHash. */ /* * 2. Restore auxiliary sessions */ /* * 3. Command specific initializations */ tool_rc rc = tool_rc_success; TPM2_HANDLE handle; bool result = tpm2_util_string_to_uint32(ctx.session_path, &handle); if (result) { rc = tpm2_util_sys_handle_to_esys_handle(ectx, handle, &ctx.session_handle); if (rc != tool_rc_success) { return rc; } } else { rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } ctx.session_handle = tpm2_session_get_handle(ctx.session); } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ /* * 4.b Determine if TPM2_CC_ is to be dispatched */ return tool_rc_success; } static tool_rc check_options(void) { if (!ctx.session_path) { LOG_ERR("Specify the session context."); return tool_rc_option_error; } return tool_rc_success; } static bool on_option(char key, char *value) { UNUSED(key); switch (key) { case 'o': ctx.output_file = value; break; case 0: ctx.hex = true; break; case 'S': ctx.session_path = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "output", required_argument, NULL, 'o' }, { "hex", no_argument, NULL, 0 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:o:", ARRAY_LEN(topts), topts, on_option, 0, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = get_policydigest(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_outputs(); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ free(ctx.policy_digest); /* * 2. Close authorization sessions */ return tpm2_session_close(&ctx.session); /* * 3. Close auxiliary sessions */ } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getpolicydigest", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_getrandom.c000066400000000000000000000231301412464516500176350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_capability.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_util.h" typedef struct tpm_random_ctx tpm_random_ctx; #define MAX_AUX_SESSIONS 3 #define MAX_SESSIONS 3 struct tpm_random_ctx { /* * Input options */ UINT16 num_of_bytes; bool force; bool hex; /* * Outputs */ char *output_file; TPM2B_DIGEST *random_bytes; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; TPMI_ALG_HASH parameter_hash_algorithm; bool is_command_dispatch; /* * Aux Sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_random_ctx ctx = { .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, .aux_session_handle[2] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; static tool_rc get_random(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ tool_rc rc = tpm2_getrandom(ectx, ctx.num_of_bytes, &ctx.random_bytes, &ctx.cp_hash, &ctx.rp_hash, ctx.aux_session_handle[0], ctx.aux_session_handle[1], ctx.aux_session_handle[2], ctx.parameter_hash_algorithm); if (rc != tool_rc_success) { LOG_ERR("Failed getrandom"); } return rc; } static tool_rc process_outputs(void) { /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ /* ensure we got the expected number of bytes unless force is set */ tool_rc rc = tool_rc_success; if (!ctx.force && ctx.random_bytes->size != ctx.num_of_bytes) { LOG_ERR("Got %"PRIu16" bytes, expected: %"PRIu16"\n" "Lower your requested amount or" " use --force to override this behavior", ctx.random_bytes->size, ctx.num_of_bytes); rc = tool_rc_general_error; goto out_skip_output_file; } /* * Either open an output file, or if stdout, do nothing as -Q * was specified. */ FILE *out = stdout; if (ctx.output_file) { out = fopen(ctx.output_file, "wb+"); if (!out) { LOG_ERR("Could not open output file \"%s\", error: %s", ctx.output_file, strerror(errno)); rc = tool_rc_general_error; goto out; } } else if (!output_enabled) { goto out; } if (ctx.hex) { tpm2_util_print_tpm2b2(out, ctx.random_bytes); goto out; } is_file_op_success = files_write_bytes(out, ctx.random_bytes->buffer, ctx.random_bytes->size); if (!is_file_op_success) { rc = tool_rc_general_error; goto out; } if(ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); if (!is_file_op_success) { rc = tool_rc_general_error; } } out: if (out && out != stdout) { fclose(out); } out_skip_output_file: if (!ctx.cp_hash_path) { free(ctx.random_bytes); } return rc; } static tool_rc get_max_random(ESYS_CONTEXT *ectx, UINT32 *value) { TPMS_CAPABILITY_DATA *cap_data = NULL; tool_rc rc = tpm2_capability_get(ectx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES, &cap_data); if (rc != tool_rc_success) { return rc; } UINT32 i; for (i = 0; i < cap_data->data.tpmProperties.count; i++) { TPMS_TAGGED_PROPERTY *p = &cap_data->data.tpmProperties.tpmProperty[i]; if (p->property == TPM2_PT_MAX_DIGEST) { *value = p->value; free(cap_data); return tool_rc_success; } } LOG_ERR("TPM does not have property TPM2_PT_MAX_DIGEST"); free(cap_data); return tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions * Note: Old-auth value is ignored when calculating cpHash. */ /* * 2. Restore auxiliary sessions */ tool_rc rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ /* * Error if bytes requested is bigger than max hash size, which is what TPMs * should bound their requests by and always have available per the spec. * * Per 16.1 of: * - https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf * * Allow the force flag to override this behavior. */ if (!ctx.force) { UINT32 max = 0; rc = get_max_random(ectx, &max); if (rc != tool_rc_success) { return rc; } if (ctx.num_of_bytes > max) { LOG_ERR("TPM getrandom is bounded by max hash size, which is: " "%"PRIu32"\n" "Please lower your request (preferred) and try again or" " use --force (advanced)", max); return tool_rc_general_error; } } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.aux_session[0], ctx.aux_session[1], ctx.aux_session[2] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static bool on_option(char key, char *value) { UNUSED(key); switch (key) { case 'f': ctx.force = true; break; case 'o': ctx.output_file = value; break; case 0: ctx.hex = true; break; case 1: ctx.cp_hash_path = value; break; case 2: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; /* no default */ } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Only supports one SIZE octets, got: %d", argc); return false; } bool result = tpm2_util_string_to_uint16(argv[0], &ctx.num_of_bytes); if (!result) { LOG_ERR("Error converting size to a number, got: \"%s\".", argv[0]); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "output", required_argument, NULL, 'o' }, { "force", required_argument, NULL, 'f' }, { "hex", no_argument, NULL, 0 }, { "session", required_argument, NULL, 'S' }, { "cphash", required_argument, NULL, 1 }, { "rphash", required_argument, NULL, 2 } }; *opts = tpm2_options_new("S:o:f", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ /* * 2. Process inputs */ tool_rc rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = get_random(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_outputs(); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ /* * 3. Close auxiliary sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tool_rc_success; size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); } if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getrandom", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_getsessionauditdigest.c000066400000000000000000000165001412464516500222720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_tool.h" typedef struct tpm_getsessionauditdigest_ctx tpm_getsessionauditdigest_ctx; struct tpm_getsessionauditdigest_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } key; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } endorsement_hierarchy; char *signature_path; char *message_path; tpm2_convert_sig_fmt sig_format; TPMI_ALG_HASH sig_hash_algorithm; TPM2B_DATA qualification_data; TPM2B_ATTEST *audit_info; TPMT_SIGNATURE *signature; TPMT_SIG_SCHEME in_scheme; tpm2_session *audit_session; const char *audit_session_path; ESYS_TR audit_session_handle; }; static tpm_getsessionauditdigest_ctx ctx = { .sig_hash_algorithm = TPM2_ALG_NULL, .qualification_data = TPM2B_EMPTY_INIT, .endorsement_hierarchy = { .ctx_path = "e" }, .in_scheme = { .scheme = TPM2_ALG_NULL, }, .audit_session_handle = ESYS_TR_NONE, }; static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.endorsement_hierarchy.auth_str = value; break; case 'c': ctx.key.ctx_path = value; break; case 'p': ctx.key.auth_str = value; break; case 'q': ctx.qualification_data.size = sizeof(ctx.qualification_data.buffer); return tpm2_util_bin_from_hex_or_file(value, &ctx.qualification_data.size, ctx.qualification_data.buffer); break; case 's': ctx.signature_path = value; break; case 'm': ctx.message_path = value; break; case 'f': ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } break; case 'g': ctx.sig_hash_algorithm = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.sig_hash_algorithm == TPM2_ALG_ERROR) { LOG_ERR( "Could not convert signature hash algorithm selection, got: \"%s\"", value); return false; } break; case 'S': ctx.audit_session_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "hierarchy-auth", required_argument, NULL, 'P' }, { "key-context", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "qualification", required_argument, NULL, 'q' }, { "signature", required_argument, NULL, 's' }, { "message", required_argument, NULL, 'm' }, { "format", required_argument, NULL, 'f' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "session", required_argument, NULL, 'S' } }; *opts = tpm2_options_new("S:P:c:p:q:s:m:f:g:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool check_input_options_and_args(void) { if (!ctx.key.ctx_path) { LOG_ERR("Specify the signing key to use for signing attestation."); return false; } if (!ctx.signature_path) { LOG_ERR("Specify the file path to store the signature of the attestation data."); return false; } if (!ctx.message_path) { LOG_ERR("Specify the file path to store the attestation data."); return false; } if (!ctx.audit_session_path) { LOG_ERR("Specify the session to be used to start audit."); return false; } return true; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { tool_rc rc = tpm2_session_restore(ectx, ctx.audit_session_path, false, &ctx.audit_session); if (rc != tool_rc_success) { LOG_ERR("Could not restore audit session"); return rc; } ctx.audit_session_handle = tpm2_session_get_handle(ctx.audit_session); /* * Load auths */ rc = tpm2_util_object_load_auth(ectx, ctx.endorsement_hierarchy.ctx_path, ctx.endorsement_hierarchy.auth_str, &ctx.endorsement_hierarchy.object, false, TPM2_HANDLE_FLAGS_E); if (rc != tool_rc_success) { LOG_ERR("Invalid endorsement hierarchy authorization"); return rc; } rc = tpm2_util_object_load_auth(ectx, ctx.key.ctx_path, ctx.key.auth_str, &ctx.key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } /* * Setup signature scheme */ rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.key.object.tr_handle, &ctx.sig_hash_algorithm, TPM2_ALG_NULL, &ctx.in_scheme); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc process_outputs(ESYS_CONTEXT *ectx) { UNUSED(ectx); bool result = true; if (ctx.signature_path) { result = tpm2_convert_sig_save(ctx.signature, ctx.sig_format, ctx.signature_path); } if (!result) { LOG_ERR("Failed to save the signature data."); return tool_rc_general_error; } if (ctx.message_path) { result = files_save_bytes_to_file(ctx.message_path, (UINT8*) ctx.audit_info->attestationData, ctx.audit_info->size); } if (!result) { LOG_ERR("Failed to save the attestation data."); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); //Check input arguments bool result = check_input_options_and_args(); if (!result) { return tool_rc_option_error; } //Process inputs tool_rc rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } //ESAPI call rc = tpm2_getsessionauditdigest(ectx, &ctx.endorsement_hierarchy.object, &ctx.key.object, &ctx.in_scheme, &ctx.qualification_data, &ctx.audit_info, &ctx.signature, ctx.audit_session_handle); if (rc != tool_rc_success) { return rc; } //Process Outputs rc = process_outputs(ectx); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tpm2_session_close(&ctx.audit_session); if (rc != tool_rc_success) { LOG_ERR("Failed closing audit session."); } rc = tpm2_session_close(&ctx.key.object.session); if (rc != tool_rc_success) { LOG_ERR("Failed closing auth session for signing key handle."); } rc = tpm2_session_close(&ctx.endorsement_hierarchy.object.session); if (rc != tool_rc_success) { LOG_ERR("Failed closing auth session for endorsement hierarchy handle."); } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("getsessionauditdigest", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_gettestresult.c000066400000000000000000000035061412464516500206000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tool_rc_general_error; TPM2_RC status; TPM2B_MAX_BUFFER *output = NULL; /* * If TPM2_SelfTest() has not been executed and a testable function has not been tested, testResult will be * TPM_RC_NEEDS_TEST. If TPM2_SelfTest() has been received and the tests are not complete, * testResult will be TPM_RC_TESTING. If testing of all functions is complete without functional failures, * testResult will be TPM_RC_SUCCESS. If any test failed, testResult will be TPM_RC_FAILURE. */ tool_rc tmp_rc = tpm2_gettestresult(ectx, &output, &status); if (tmp_rc != tool_rc_success) { return tmp_rc; } tpm2_tool_output("status: "); print_yaml_indent(1); status &= TPM2_RC_TESTING; switch (status) { case TPM2_RC_SUCCESS: tpm2_tool_output("success"); break; case TPM2_RC_TESTING: tpm2_tool_output("testing"); break; case TPM2_RC_NEEDS_TEST: tpm2_tool_output("needs-test"); break; default: LOG_ERR("Unknown testing result, got: 0x%x", status); goto out; } if (output->size > 0) { tpm2_tool_output("\ndata: "); print_yaml_indent(1); tpm2_util_hexdump(output->buffer, output->size); } tpm2_tool_output("\n"); rc = tool_rc_success; out: free(output); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("gettestresult", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_gettime.c000066400000000000000000000157051412464516500173240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_hash.h" #include "tpm2_options.h" typedef struct tpm_gettime_ctx tpm_gettime_ctx; struct tpm_gettime_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } privacy_admin; tpm2_convert_sig_fmt sig_format; TPM2B_DATA qualifying_data; TPMI_ALG_HASH halg; TPMI_ALG_SIG_SCHEME sig_scheme; TPMT_SIG_SCHEME in_scheme; const char *certify_info_path; const char *output_path; char *cp_hash_path; }; static tpm_gettime_ctx ctx = { .halg = TPM2_ALG_NULL, .sig_scheme = TPM2_ALG_NULL, .privacy_admin = { .ctx_path = "endorsement" } }; static tool_rc init(ESYS_CONTEXT *ectx) { if (!ctx.signing_key.ctx_path) { LOG_ERR("Expected option \"-c\""); return tool_rc_option_error; } if (ctx.cp_hash_path && (ctx.output_path || ctx.certify_info_path)) { LOG_ERR("Ignoring output options due to cpHash calculation"); return tool_rc_option_error; } /* load the signing key */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } /* * Set signature scheme for key type, or validate chosen scheme is allowed for key type. */ rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.signing_key.object.tr_handle, &ctx.halg, ctx.sig_scheme, &ctx.in_scheme); if (rc != tool_rc_success) { LOG_ERR("bad signature scheme for key type!"); return rc; } /* set up the privacy admin (always endorsement) hard coded in ctx init */ rc = tpm2_util_object_load_auth(ectx, ctx.privacy_admin.ctx_path, ctx.privacy_admin.auth_str, &ctx.privacy_admin.object, false, TPM2_HANDLE_FLAGS_E); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.signing_key.ctx_path = value; break; case 'p': ctx.signing_key.auth_str = value; break; case 'P': ctx.privacy_admin.auth_str = value; break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Could not convert to number or lookup algorithm, got: " "\"%s\"", value); return false; } break; case 's': { ctx.sig_scheme = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.sig_scheme == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } } break; case 'o': ctx.output_path = value; break; case 'f': ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } break; case 'q': ctx.qualifying_data.size = sizeof(ctx.qualifying_data.buffer); return tpm2_util_bin_from_hex_or_file(value, &ctx.qualifying_data.size, ctx.qualifying_data.buffer); break; case 2: ctx.certify_info_path = value; break; case 0: ctx.cp_hash_path = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "endorse-auth", required_argument, NULL, 'P' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "scheme", required_argument, NULL, 's' }, { "signature", required_argument, NULL, 'o' }, { "key-context", required_argument, NULL, 'c' }, { "format", required_argument, NULL, 'f' }, { "qualification", required_argument, NULL, 'q' }, { "attestation", required_argument, NULL, 2 }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("p:g:o:c:f:s:P:q:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = init(ectx); if (rc != tool_rc_success) { return rc; } TPM2B_ATTEST *time_info = NULL; TPMT_SIGNATURE *signature = NULL; if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_gettime(ectx, &ctx.privacy_admin.object, &ctx.signing_key.object, &ctx.qualifying_data, &ctx.in_scheme, &time_info, &signature, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } rc = tpm2_gettime(ectx, &ctx.privacy_admin.object, &ctx.signing_key.object, &ctx.qualifying_data, &ctx.in_scheme, &time_info, &signature, NULL); if (rc != tool_rc_success) { return rc; } /* save the signature */ if (ctx.output_path) { bool result = tpm2_convert_sig_save(signature, ctx.sig_format, ctx.output_path); if (!result) { rc = tool_rc_general_error; goto out; } } if (ctx.certify_info_path) { /* save the attestation data */ bool result = files_save_bytes_to_file(ctx.certify_info_path, time_info->attestationData, time_info->size); if (!result) { rc = tool_rc_general_error; goto out; } } TPMS_ATTEST attest; rc = files_tpm2b_attest_to_tpms_attest(time_info, &attest); if (rc == tool_rc_success) { tpm2_util_print_time(&attest.attested.time.time); } out: Esys_Free(time_info); Esys_Free(signature); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tpm2_session_close(&ctx.privacy_admin.object.session); rc |=tpm2_session_close(&ctx.signing_key.object.session); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("gettime", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_hash.c000066400000000000000000000076471412464516500166170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_hash.h" #include "tpm2_hierarchy.h" #include "tpm2_tool.h" typedef struct tpm_hash_ctx tpm_hash_ctx; struct tpm_hash_ctx { TPMI_RH_HIERARCHY hierarchy_value; FILE *input_file; TPMI_ALG_HASH halg; char *output_hash_path; char *output_ticket_path; bool hex; }; static tpm_hash_ctx ctx = { .hierarchy_value = TPM2_RH_OWNER, .halg = TPM2_ALG_SHA1, }; static tool_rc hash_and_save(ESYS_CONTEXT *context) { TPM2B_DIGEST *out_hash; TPMT_TK_HASHCHECK *validation; FILE *out = stdout; tool_rc rc = tpm2_hash_file(context, ctx.halg, ctx.hierarchy_value, ctx.input_file, &out_hash, &validation); if (rc != tool_rc_success) { return rc; } if (ctx.output_ticket_path) { bool res = files_save_validation(validation, ctx.output_ticket_path); if (!res) { rc = tool_rc_general_error; goto out; } } rc = tool_rc_general_error; if (ctx.output_hash_path) { out = fopen(ctx.output_hash_path, "wb+"); if (!out) { LOG_ERR("Could not open output file \"%s\", error: %s", ctx.output_hash_path, strerror(errno)); goto out; } } else if (!output_enabled) { rc = tool_rc_success; goto out; } if (ctx.hex) { tpm2_util_print_tpm2b2(out, out_hash); } else { bool res = files_write_bytes(out, out_hash->buffer, out_hash->size); if (!res) { goto out; } } rc = tool_rc_success; out: if (out && out != stdout) { fclose(out); } free(out_hash); free(validation); return rc; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Only supports one hash input file, got: %d", argc); return false; } ctx.input_file = fopen(argv[0], "rb"); if (!ctx.input_file) { LOG_ERR("Could not open input file \"%s\", error: %s", argv[0], strerror(errno)); return false; } return true; } static bool on_option(char key, char *value) { bool res; switch (key) { case 'C': res = tpm2_util_handle_from_optarg(value, &ctx.hierarchy_value, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); if (!res) { return false; } break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { return false; } break; case 'o': ctx.output_hash_path = value; break; case 't': ctx.output_ticket_path = value; break; case 0: ctx.hex = true; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { {"hierarchy", required_argument, NULL, 'C'}, {"hash-algorithm", required_argument, NULL, 'g'}, {"output", required_argument, NULL, 'o'}, {"ticket", required_argument, NULL, 't'}, {"hex", no_argument, NULL, 0 }, }; /* set up non-static defaults here */ ctx.input_file = stdin; *opts = tpm2_options_new("C:g:o:t:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); return hash_and_save(context); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *context) { UNUSED(context); if (ctx.input_file) { fclose(ctx.input_file); } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("hash", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_hierarchycontrol.c000066400000000000000000000157011412464516500212410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "tpm2_tool.h" #include "files.h" typedef struct hierarchycontrol_ctx hierarchycontrol_ctx; struct hierarchycontrol_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPMI_RH_ENABLES enable; TPMI_YES_NO state; char *cp_hash_path; }; static hierarchycontrol_ctx ctx = { .auth_hierarchy.ctx_path = "p", }; static tool_rc hierarchycontrol(ESYS_CONTEXT *ectx) { if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_hierarchycontrol(ectx, &ctx.auth_hierarchy.object, ctx.enable, ctx.state, &cp_hash); if (rc == tool_rc_success) { bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { LOG_ERR("Failed to save cp hash"); rc = tool_rc_general_error; } } return rc; } LOG_INFO ("Using hierarchy %s to \'%s\' TPMA_STARTUP_CLEAR bit (%s)", ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_OWNER ? "TPM2_RH_OWNER" : ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_ENDORSEMENT ? "TPM2_RH_ENDORSEMENT" : ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_PLATFORM ? "TPM2_RH_PLATFORM" : "TPM2_RH_PLATFORM_NV", ctx.enable == TPM2_RH_PLATFORM ? "phEnable" : ctx.enable == TPM2_RH_OWNER ? "shEnable" : ctx.enable == TPM2_RH_ENDORSEMENT ? "ehEnable" : "phEnableNV", ctx.state ? "SET" : "CLEAR"); tool_rc rc = tpm2_hierarchycontrol(ectx, &ctx.auth_hierarchy.object, ctx.enable, ctx.state, NULL); if (rc != tool_rc_success) { LOG_ERR("Failed hierarchycontrol operation."); } return rc; } static bool on_arg(int argc, char **argv) { switch (argc) { case 2: break; default: return false; } if (!strcmp(argv[0], "phEnable")) { ctx.enable = TPM2_RH_PLATFORM; } else if (!strcmp(argv[0], "shEnable")) { ctx.enable = TPM2_RH_OWNER; } else if (!strcmp(argv[0], "ehEnable")) { ctx.enable = TPM2_RH_ENDORSEMENT; } else if (!strcmp(argv[0], "phEnableNV")) { ctx.enable = TPM2_RH_PLATFORM_NV; } else { LOG_ERR("Incorrect property, got: \"%s\", expected " "[phEnable|shEnable|ehEnable|phEnableNV]", argv[0]); return false; } if (!strcmp(argv[1], "set")) { ctx.state = TPM2_YES; } else if (!strcmp(argv[1], "clear")) { ctx.state = TPM2_NO; } else { LOG_ERR("Incorrect operation, got: \"%s\", expected [set|clear].", argv[1]); return false; } return true; } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "hierarchy-auth", required_argument, NULL, 'P' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_P | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_E); if (rc != tool_rc_success) { LOG_ERR("Invalid authorization"); return rc; } if (ctx.state == TPM2_YES) { switch (ctx.enable) { case TPM2_RH_PLATFORM: LOG_ERR("phEnable may not be SET using this command"); return tool_rc_tcti_error; case TPM2_RH_OWNER: case TPM2_RH_ENDORSEMENT: case TPM2_RH_PLATFORM_NV: if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) { LOG_ERR("Only platform hierarchy handle can be specified for " "SET \'%s\' bit", ctx.enable == TPM2_RH_OWNER ? "shEnable" : ctx.enable == TPM2_RH_ENDORSEMENT ? "ehEnable" : ctx.enable == TPM2_RH_PLATFORM_NV ? "phEnableNV" : "NONE"); return tool_rc_auth_error; } break; default: LOG_ERR("Unknown permanent handle, got: \"0x%x\"", ctx.enable); return tool_rc_unsupported; } } else { switch (ctx.enable) { case TPM2_RH_PLATFORM: if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) { LOG_ERR("Only platform hierarchy handle can be specified for " "CLEAR \'phEnable\' bit"); return tool_rc_general_error; } break; case TPM2_RH_OWNER: if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_OWNER && ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) { LOG_ERR("Only platform and owner hierarchy handle can be " "specified for CLEAR \'shEnable\' bit"); return tool_rc_auth_error; } break; case TPM2_RH_ENDORSEMENT: if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_ENDORSEMENT && ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) { LOG_ERR( "Only platform and endorsement hierarchy handle can be " "specified for CLEAR \'ehEnable\' bit"); return tool_rc_auth_error; } break; case TPM2_RH_PLATFORM_NV: if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM_NV && ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) { LOG_ERR( "Only platform hierarchy handle can be specified for " "CLEAR \'phEnableNV\' bit"); return tool_rc_auth_error; } break; default: LOG_ERR("Unknown permanent handle, got: \"0x%x\"", ctx.enable); return tool_rc_unsupported; } } return hierarchycontrol(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("hierarchycontrol", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_hmac.c000066400000000000000000000217301412464516500165710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_tool.h" typedef struct tpm_hmac_ctx tpm_hmac_ctx; struct tpm_hmac_ctx { struct { char *ctx_path; char *auth_str; tpm2_loaded_object object; } hmac_key; FILE *input; char *hmac_output_file_path; char *ticket_path; TPMI_ALG_HASH halg; bool hex; char *cp_hash_path; }; static tpm_hmac_ctx ctx; static tool_rc tpm_hmac_file(ESYS_CONTEXT *ectx, TPM2B_DIGEST **result, TPMT_TK_HASHCHECK **validation) { unsigned long file_size = 0; FILE *input = ctx.input; tool_rc rc; /* Suppress error reporting with NULL path */ bool res = files_get_file_size(input, &file_size, NULL); /* * If we can get the file size and its less than 1024, just do it in one hash invocation. * We can't use the one-shot command if we require ticket, as it doesn't provide it in * the response from the TPM. */ if (!ctx.ticket_path && res && file_size <= TPM2_MAX_DIGEST_BUFFER) { TPM2B_MAX_BUFFER buffer = { .size = file_size }; res = files_read_bytes(ctx.input, buffer.buffer, buffer.size); if (!res) { LOG_ERR("Error reading input file!"); return tool_rc_general_error; } if (ctx.cp_hash_path) { LOG_WARN("Exiting without performing HMAC when calculating cpHash"); TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_hmac(ectx, &ctx.hmac_key.object, ctx.halg, &buffer, result, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } /* * hash algorithm specified in the key's scheme is used as the * hash algorithm for the HMAC */ return tpm2_hmac(ectx, &ctx.hmac_key.object, ctx.halg, &buffer, result, NULL); } if (ctx.cp_hash_path) { LOG_ERR("Cannot calculate cpHash for buffers requiring HMAC sequence."); return tool_rc_general_error; } ESYS_TR sequence_handle; /* * Size is either unknown because the FILE * is a fifo, or it's too big * to do in a single hash call. Based on the size figure out the chunks * to loop over, if possible. This way we can call Complete with data. */ rc = tpm2_hmac_start(ectx, &ctx.hmac_key.object, ctx.halg, &sequence_handle); if (rc != tool_rc_success) { return rc; } /* If we know the file size, we decrement the amount read and terminate the * loop when 1 block is left, else we go till feof. */ size_t left = file_size; bool use_left = !!res; TPM2B_MAX_BUFFER data; bool done = false; while (!done) { size_t bytes_read = fread(data.buffer, 1, BUFFER_SIZE(typeof(data), buffer), input); if (ferror(input)) { LOG_ERR("Error reading from input file"); return tool_rc_general_error; } data.size = bytes_read; /* if data was read, update the sequence */ rc = tpm2_hmac_sequenceupdate(ectx, sequence_handle, &ctx.hmac_key.object, &data); if (rc != tool_rc_success) { return rc; } if (use_left) { left -= bytes_read; if (left <= TPM2_MAX_DIGEST_BUFFER) { done = true; continue; } } else if (feof(input)) { done = true; } } /* end file read/hash update loop */ if (use_left) { data.size = left; bool res = files_read_bytes(input, data.buffer, left); if (!res) { LOG_ERR("Error reading from input file."); return tool_rc_general_error; } } else { data.size = 0; } rc = tpm2_hmac_sequencecomplete(ectx, sequence_handle, &ctx.hmac_key.object, &data, result, validation); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc do_hmac_and_output(ESYS_CONTEXT *ectx) { TPM2B_DIGEST *hmac_out = NULL; TPMT_TK_HASHCHECK *validation = NULL; FILE *out = stdout; tool_rc rc = tpm_hmac_file(ectx, &hmac_out, &validation); if (rc != tool_rc_success || ctx.cp_hash_path) { goto out; } assert(hmac_out); if (ctx.ticket_path) { bool res = files_save_validation(validation, ctx.ticket_path); if (!res) { rc = tool_rc_general_error; goto out; } } rc = tool_rc_general_error; if (ctx.hmac_output_file_path) { out = fopen(ctx.hmac_output_file_path, "wb+"); if (!out) { LOG_ERR("Could not open output file \"%s\", error: %s", ctx.hmac_output_file_path, strerror(errno)); goto out; } } else if (!output_enabled) { rc = tool_rc_success; goto out; } if (ctx.hex) { tpm2_util_print_tpm2b2(out, hmac_out); } else { bool res = files_write_bytes(out, hmac_out->buffer, hmac_out->size); if (!res) { goto out; } } rc = tool_rc_success; out: if (out && out != stdout) { fclose(out); } free(hmac_out); free(validation); return rc; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.hmac_key.ctx_path = value; break; case 'p': ctx.hmac_key.auth_str = value; break; case 'o': ctx.hmac_output_file_path = value; break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { return false; } break; case 't': ctx.ticket_path = value; break; case 0: ctx.hex = true; break; case 1: ctx.cp_hash_path = value; break; /* no default */ } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Expected 1 hmac input file, got: %d", argc); return false; } ctx.input = fopen(argv[0], "rb"); if (!ctx.input) { LOG_ERR("Error opening file \"%s\", error: %s", argv[0], strerror(errno)); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "key-context", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "output", required_argument, NULL, 'o' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "ticket", required_argument, NULL, 't' }, { "hex", no_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, }; ctx.input = stdin; *opts = tpm2_options_new("c:p:o:g:t:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc readpub(ESYS_CONTEXT *ectx, ESYS_TR handle, TPM2B_PUBLIC **public) { return tpm2_readpublic(ectx, handle, public, NULL, NULL); } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * Option C must be specified. */ if (!ctx.hmac_key.ctx_path) { LOG_ERR("Must specify options C."); return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.hmac_key.ctx_path, ctx.hmac_key.auth_str, &ctx.hmac_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid key handle authorization"); return rc; } /* * if no halg was specified, read the public portion of the key and use it's * scheme */ if (!ctx.halg) { TPM2B_PUBLIC *pub = NULL; rc = readpub(ectx, ctx.hmac_key.object.tr_handle, &pub); if (rc != tool_rc_success) { return rc; } /* * if we're attempting to figure out a hashing scheme, and the scheme is NULL * we default to sha256. */ ctx.halg = pub->publicArea.parameters.keyedHashDetail.scheme.details.hmac.hashAlg; if (ctx.halg == TPM2_ALG_NULL) { ctx.halg = TPM2_ALG_SHA256; } free(pub); } return do_hmac_and_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (ctx.input && ctx.input != stdin) { fclose(ctx.input); } return tpm2_session_close(&ctx.hmac_key.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("hmac", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_import.c000066400000000000000000000451641412464516500172020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ //**********************************************************************; // Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. // Licensed under the Apache License 2.0 (the "License"). You may not use // this file except in compliance with the License. You can obtain a copy // in the file LICENSE in the source distribution or at // https://www.openssl.org/source/license.html // // EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) // // See Victor Shoup, "OAEP reconsidered," Nov. 2000, for problems with the security // proof for the original OAEP scheme, which EME-OAEP is based on. A new // proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern, // "RSA-OEAP is Still Alive!", Dec. 2000, . // The new proof has stronger requirements for the underlying permutation: // "partial-one-wayness" instead of one-wayness. For the RSA function, this // is an equivalent notion. //**********************************************************************; #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_auth_util.h" #include "tpm2_errata.h" #include "tpm2_identity_util.h" #include "tpm2_openssl.h" #include "tpm2_options.h" typedef struct tpm_import_ctx tpm_import_ctx; struct tpm_import_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } parent; char *input_key_file; char *public_key_file; char *private_key_file; char *parent_key_public_file; char *name_alg; char *attrs; /* The attributes to use */ char *key_auth_str; char *passin; /* an optional auth string for the input key file for OSSL */ char *input_seed_file; char *input_enc_key_file; char *policy; bool import_tpm; /* Any param that is exclusively used by import tpm object sets this flag */ char *object_alg; char *cp_hash_path; }; static tpm_import_ctx ctx; static tool_rc readpublic(ESYS_CONTEXT *ectx, ESYS_TR handle, TPM2B_PUBLIC **public) { return tpm2_readpublic(ectx, handle, public, NULL, NULL); } static bool create_import_key_private_data(TPM2B_PRIVATE *private, TPMI_ALG_HASH parent_name_alg, TPM2B_MAX_BUFFER *encrypted_duplicate_sensitive, TPM2B_DIGEST *outer_hmac) { //UINT16 hash_size = tpm2_alg_util_get_hash_size(ctx.name_alg); UINT16 parent_hash_size = tpm2_alg_util_get_hash_size(parent_name_alg); private->size = sizeof(parent_hash_size) + parent_hash_size + encrypted_duplicate_sensitive->size; size_t hmac_size_offset = 0; TSS2_RC rval = Tss2_MU_UINT16_Marshal(parent_hash_size, private->buffer, sizeof(parent_hash_size), &hmac_size_offset); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("Error serializing parent hash size"); return false; } memcpy(private->buffer + hmac_size_offset, outer_hmac->buffer, parent_hash_size); memcpy(private->buffer + hmac_size_offset + parent_hash_size, encrypted_duplicate_sensitive->buffer, encrypted_duplicate_sensitive->size); return true; } static tool_rc key_import(ESYS_CONTEXT *ectx, TPM2B_PUBLIC *parent_pub, TPM2B_SENSITIVE *privkey, TPM2B_PUBLIC *pubkey, TPM2B_ENCRYPTED_SECRET *encrypted_seed, TPM2B_PRIVATE **imported_private) { TPMI_ALG_HASH name_alg = pubkey->publicArea.nameAlg; TPM2B_DIGEST *seed = &privkey->sensitiveArea.seedValue; /* * Create the protection encryption key that gets encrypted with the parents public key. */ TPM2B_DATA enc_sensitive_key = { .size = parent_pub->publicArea.parameters.rsaDetail.symmetric.keyBits.sym / 8 }; if(enc_sensitive_key.size < 16) { LOG_ERR("Calculated wrapping keysize is less than 16 bytes, got: %u", enc_sensitive_key.size); return tool_rc_general_error; } int ossl_rc = RAND_bytes(enc_sensitive_key.buffer, enc_sensitive_key.size); if (ossl_rc != 1) { LOG_ERR("RAND_bytes failed: %s", ERR_error_string(ERR_get_error(), NULL)); return tool_rc_general_error; } /* * Calculate the object name. */ TPM2B_NAME pubname = TPM2B_TYPE_INIT(TPM2B_NAME, name); bool res = tpm2_identity_create_name(pubkey, &pubname); if (!res) { return tool_rc_general_error; } TPM2B_MAX_BUFFER hmac_key; TPM2B_MAX_BUFFER enc_key; res = tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key( parent_pub, &pubname, seed, &hmac_key, &enc_key); if (!res) { return tool_rc_general_error; } TPM2B_MAX_BUFFER encrypted_inner_integrity = TPM2B_EMPTY_INIT; res = tpm2_identity_util_calculate_inner_integrity(name_alg, privkey, &pubname, &enc_sensitive_key, &parent_pub->publicArea.parameters.rsaDetail.symmetric, &encrypted_inner_integrity); if (!res) { return tool_rc_general_error; } TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT; TPM2B_MAX_BUFFER encrypted_duplicate_sensitive = TPM2B_EMPTY_INIT; tpm2_identity_util_calculate_outer_integrity(parent_pub->publicArea.nameAlg, &pubname, &encrypted_inner_integrity, &hmac_key, &enc_key, &parent_pub->publicArea.parameters.rsaDetail.symmetric, &encrypted_duplicate_sensitive, &outer_hmac); TPM2B_PRIVATE private = TPM2B_EMPTY_INIT; res = create_import_key_private_data(&private, parent_pub->publicArea.nameAlg, &encrypted_duplicate_sensitive, &outer_hmac); if (!res) { return tool_rc_general_error; } TPMT_SYM_DEF_OBJECT *sym_alg = &parent_pub->publicArea.parameters.rsaDetail.symmetric; if (!ctx.cp_hash_path) { return tpm2_import(ectx, &ctx.parent.object, &enc_sensitive_key, pubkey, &private, encrypted_seed, sym_alg, imported_private, NULL); } TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_import(ectx, &ctx.parent.object, &enc_sensitive_key, pubkey, &private, encrypted_seed, sym_alg, imported_private, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.parent.auth_str = value; break; case 'p': ctx.key_auth_str = value; break; case 'G': ctx.object_alg = value; return true; case 'i': ctx.input_key_file = value; break; case 'C': ctx.parent.ctx_path = value; break; case 'U': ctx.parent_key_public_file = value; break; case 'k': ctx.import_tpm = true; ctx.input_enc_key_file = value; break; case 'u': ctx.public_key_file = value; break; case 'r': ctx.private_key_file = value; break; case 'a': ctx.attrs = value; break; case 'g': ctx.name_alg = value; break; case 's': ctx.import_tpm = true; ctx.input_seed_file = value; break; case 'L': ctx.policy = value; break; case 0: ctx.passin = value; break; case 1: ctx.cp_hash_path = value; break; default: LOG_ERR("Invalid option"); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "parent-auth", required_argument, NULL, 'P'}, { "key-auth", required_argument, NULL, 'p'}, { "key-algorithm", required_argument, NULL, 'G'}, { "input", required_argument, NULL, 'i'}, { "parent-context", required_argument, NULL, 'C'}, { "parent-public", required_argument, NULL, 'U'}, { "private", required_argument, NULL, 'r'}, { "public", required_argument, NULL, 'u'}, { "attributes", required_argument, NULL, 'a'}, { "hash-algorithm", required_argument, NULL, 'g'}, { "seed", required_argument, NULL, 's'}, { "policy", required_argument, NULL, 'L'}, { "encryption-key", required_argument, NULL, 'k'}, { "passin", required_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("P:p:G:i:C:U:u:r:a:g:s:L:k:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } /** * Check all options and report as many errors as possible via LOG_ERR. * @return * tool_rc indicating error. */ static tool_rc check_options(void) { tool_rc rc = tool_rc_success; /* Check the tpm import specific options */ if (ctx.import_tpm) { if (!ctx.input_seed_file) { LOG_ERR("Expected SymSeed to be specified via \"-s\"," " missing option."); rc = tool_rc_option_error; } if (ctx.key_auth_str) { LOG_ERR("Cannot specify key password when importing a TPM key.\n" "use tpm2_changeauth after import"); rc = tool_rc_option_error; } } else { /* Openssl specific option(s) */ if (!ctx.object_alg) { LOG_ERR("Expected object type to be specified via \"-G\"," " missing option."); rc = tool_rc_option_error; } if (ctx.cp_hash_path) { LOG_WARN("CAUTION CpHash calculation includes parameters that" "have a derived/random seed!"); } } /* Common options */ if (!ctx.input_key_file) { LOG_ERR("Expected to be imported key data to be specified via \"-i\"," " missing option."); rc = tool_rc_option_error; } if (!ctx.public_key_file) { LOG_ERR("Expected output public file missing, specify \"-u\"," " missing option."); rc = tool_rc_option_error; } if (!ctx.private_key_file) { LOG_ERR("Expected output private file missing, specify \"-r\"," " missing option."); rc = tool_rc_option_error; } if (!ctx.parent.ctx_path) { LOG_ERR("Expected parent key to be specified via \"-C\"," " missing option."); rc = tool_rc_option_error; } return rc; } static void setup_default_attrs(TPMA_OBJECT *attrs, bool has_policy, bool has_auth) { /* Handle Default Setup */ *attrs = DEFAULT_CREATE_ATTRS; /* imported objects arn't created inside of the TPM so this gets turned down */ *attrs &= ~TPMA_OBJECT_SENSITIVEDATAORIGIN; *attrs &= ~TPMA_OBJECT_FIXEDTPM; *attrs &= ~TPMA_OBJECT_FIXEDPARENT; /* The default for a keyedhash object with no scheme is just for sealing */ if (!strcmp("keyedhash", ctx.object_alg)) { *attrs &= ~TPMA_OBJECT_SIGN_ENCRYPT; *attrs &= ~TPMA_OBJECT_DECRYPT; } else if (!strncmp("hmac", ctx.object_alg, 4)) { *attrs &= ~TPMA_OBJECT_DECRYPT; } /* * IMPORTANT: if the object we're creating has a policy and NO authvalue, turn off userwith auth * so empty passwords don't work on the object. */ if (has_policy && !has_auth) { *attrs &= ~TPMA_OBJECT_USERWITHAUTH; } } static tool_rc openssl_import(ESYS_CONTEXT *ectx) { /* * Load the parent public file, or read it from the TPM if not specified. * We need this information for encrypting the protection seed. */ bool free_ppub = false; tool_rc tmp_rc; tool_rc rc = tool_rc_general_error; TPM2B_PUBLIC ppub = TPM2B_EMPTY_INIT; TPM2B_PUBLIC *parent_pub = NULL; bool result; tmp_rc = tool_rc_general_error; if (ctx.parent_key_public_file) { result = files_load_public(ctx.parent_key_public_file, &ppub); parent_pub = &ppub; } else { tmp_rc = readpublic(ectx, ctx.parent.object.tr_handle, &parent_pub); free_ppub = true; result = tmp_rc == tool_rc_success; } if (!result) { LOG_ERR("Failed loading parent key public."); return tmp_rc; } TPM2B_SENSITIVE private = TPM2B_EMPTY_INIT; TPM2B_PUBLIC public = TPM2B_EMPTY_INIT; TPM2B_ENCRYPTED_SECRET encrypted_seed = TPM2B_EMPTY_INIT; /* * start with the tools default set and turn off the ones that don't make sense * If the user specified their own values, tpm2_alg_util_public_init will use that, * so this is just the default case. * */ TPMA_OBJECT attrs = 0; if (!ctx.attrs) { setup_default_attrs(&attrs, !!ctx.policy, !!ctx.key_auth_str); } /* * Backwards Compat: the tool sets name-alg by default to the parent name alg if not specified * but the tpm2_alg_util_public_init defaults to sha256. Specify the alg if not specified. */ if (!ctx.name_alg) { ctx.name_alg = (char *)tpm2_alg_util_algtostr(parent_pub->publicArea.nameAlg, tpm2_alg_util_flags_hash); if (!ctx.name_alg) { LOG_ERR("Invalid parent name algorithm, got 0x%x", parent_pub->publicArea.nameAlg); goto out; } } TPM2B_PUBLIC template = { 0 }; rc = tpm2_alg_util_public_init(ctx.object_alg, ctx.name_alg, ctx.attrs, ctx.policy, attrs, &template); if (rc != tool_rc_success) { goto out; } result = tpm2_openssl_import_keys( parent_pub, &encrypted_seed, ctx.key_auth_str, ctx.input_key_file, ctx.passin, &template, &private, &public ); if (!result) { goto out; } TPM2B_PRIVATE *imported_private = NULL; tmp_rc = key_import(ectx, parent_pub, &private, &public, &encrypted_seed, &imported_private); if (tmp_rc != tool_rc_success || ctx.cp_hash_path) { rc = tmp_rc; goto keyout; } /* * Save the public and imported_private structure to disk */ result = files_save_public(&public, ctx.public_key_file); if (!result) { goto keyout; } result = files_save_private(imported_private, ctx.private_key_file); if (!result) { goto keyout; } /* * Output the stats on the created object on Success. */ tpm2_util_public_to_yaml(&public, NULL); rc = tool_rc_success; keyout: Esys_Free(imported_private); out: if (free_ppub) { Esys_Free(parent_pub); } return rc; } static tool_rc tpm_import(ESYS_CONTEXT *ectx) { tool_rc rc = tool_rc_general_error; TPM2B_DATA enc_key = TPM2B_EMPTY_INIT; TPM2B_PUBLIC public = TPM2B_EMPTY_INIT; TPM2B_PRIVATE duplicate; TPM2B_ENCRYPTED_SECRET encrypted_seed; TPM2B_PRIVATE *imported_private = NULL; TPMT_SYM_DEF_OBJECT sym_alg = { .algorithm = TPM2_ALG_NULL }; /* Symmetric key */ if (ctx.input_enc_key_file) { enc_key.size = 16; bool result = files_load_bytes_from_path(ctx.input_enc_key_file, enc_key.buffer, &enc_key.size); if (!result) { LOG_ERR("Failed to load symmetric encryption key\"%s\"", ctx.input_enc_key_file); return tool_rc_general_error; } if (enc_key.size != 16) { LOG_ERR("Invalid AES key size, got %u bytes, expected 16", enc_key.size); return tool_rc_general_error; } sym_alg.algorithm = TPM2_ALG_AES; sym_alg.keyBits.aes = 128; sym_alg.mode.aes = TPM2_ALG_CFB; } /* Private key */ bool result = files_load_private(ctx.input_key_file, &duplicate); if (!result) { LOG_ERR("Failed to load duplicate \"%s\"", ctx.input_key_file); return tool_rc_general_error; } /* Encrypted seed */ result = files_load_encrypted_seed(ctx.input_seed_file, &encrypted_seed); if (!result) { LOG_ERR("Failed to load encrypted seed \"%s\"", ctx.input_seed_file); return tool_rc_general_error; } /* Public key */ result = files_load_public(ctx.public_key_file, &public); if (!result) { LOG_ERR(":( Failed to load public key \"%s\"", ctx.public_key_file); return tool_rc_general_error; } if (ctx.policy) { public.publicArea.authPolicy.size = sizeof(public.publicArea.authPolicy.buffer); result = files_load_bytes_from_path(ctx.policy, public.publicArea.authPolicy.buffer, &public.publicArea.authPolicy.size); if (!result) { LOG_ERR("Failed to copy over the auth policy to the public data"); return tool_rc_general_error; } } if (!ctx.cp_hash_path) { rc = tpm2_import(ectx, &ctx.parent.object, &enc_key, &public, &duplicate, &encrypted_seed, &sym_alg, &imported_private, NULL); if (rc != tool_rc_success) { return rc; } assert(imported_private); result = files_save_private(imported_private, ctx.private_key_file); Esys_Free(imported_private); if (!result) { LOG_ERR("Failed to save private key into file \"%s\"", ctx.private_key_file); return tool_rc_general_error; } return tool_rc_success; } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_import(ectx, &ctx.parent.object, &enc_key, &public, &duplicate, &encrypted_seed, &sym_alg, &imported_private, &cp_hash); if (rc != tool_rc_success) { return rc; } result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } rc = tpm2_util_object_load_auth(ectx, ctx.parent.ctx_path, ctx.parent.auth_str, &ctx.parent.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid parent key authorization"); return rc; } return ctx.import_tpm ? tpm_import(ectx) : openssl_import(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (!ctx.import_tpm) { return tool_rc_success; } return tpm2_session_close(&ctx.parent.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("import", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_incrementalselftest.c000066400000000000000000000041711412464516500217340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_tool.h" typedef struct tpm_incrementalselftest_ctx tpm_incrementalselftest_ctx; struct tpm_incrementalselftest_ctx { TPML_ALG inputalgs; }; static tpm_incrementalselftest_ctx ctx; static tool_rc do_tpm_incrementalselftest(ESYS_CONTEXT *ectx) { TPML_ALG *to_do_list = NULL; tool_rc rc = tpm2_incrementalselftest(ectx, &(ctx.inputalgs), &to_do_list); if (rc != tool_rc_success) { return rc; } tpm2_tool_output("status: "); print_yaml_indent(1); if (to_do_list->count == 0) { tpm2_tool_output("complete\n"); } else { tpm2_tool_output("success\n"); tpm2_tool_output("remaining:\n"); uint32_t i; for (i = 0; i < to_do_list->count; i++) { print_yaml_indent(1); tpm2_tool_output("%s", tpm2_alg_util_algtostr(to_do_list->algorithms[i], tpm2_alg_util_flags_any)); tpm2_tool_output("\n"); } } free(to_do_list); return tool_rc_success; } static bool on_arg(int argc, char **argv) { int i; TPM2_ALG_ID algorithm; LOG_INFO("tocheck :"); for (i = 0; i < argc; i++) { algorithm = tpm2_alg_util_from_optarg(argv[i], tpm2_alg_util_flags_any); if (algorithm == TPM2_ALG_ERROR) { LOG_INFO("\n"); LOG_ERR("Got invalid or unsupported algorithm: \"%s\"", argv[i]); return false; } ctx.inputalgs.algorithms[i] = algorithm; ctx.inputalgs.count += 1; LOG_INFO(" - %s", argv[i]); } LOG_INFO("\n"); return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); return do_tpm_incrementalselftest(ectx); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("incrementalselftest", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_load.c000066400000000000000000000114201412464516500165730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_options.h" #include "tpm2_tool.h" typedef struct tpm_load_ctx tpm_load_ctx; struct tpm_load_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } parent; struct { const char *pubpath; TPM2B_PUBLIC public; const char *privpath; TPM2B_PRIVATE private; ESYS_TR handle; } object; const char *namepath; const char *contextpath; char *cp_hash_path; }; static tpm_load_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.parent.auth_str = value; break; case 'u': ctx.object.pubpath = value; break; case 'r': ctx.object.privpath = value; break; case 'n': ctx.namepath = value; break; case 'C': ctx.parent.ctx_path = value; break; case 'c': ctx.contextpath = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "auth", required_argument, NULL, 'P' }, { "public", required_argument, NULL, 'u' }, { "private", required_argument, NULL, 'r' }, { "name", required_argument, NULL, 'n' }, { "key-context", required_argument, NULL, 'c' }, { "parent-context", required_argument, NULL, 'C' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("P:u:r:n:C:c:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc check_opts(void) { tool_rc rc = tool_rc_success; if (!ctx.parent.ctx_path) { LOG_ERR("Expected parent object via -C"); rc = tool_rc_option_error; } if (!ctx.object.pubpath) { LOG_ERR("Expected public object portion via -u"); rc = tool_rc_option_error; } if (!ctx.object.privpath) { LOG_ERR("Expected private object portion via -r"); rc = tool_rc_option_error; } if (!ctx.contextpath && !ctx.cp_hash_path) { LOG_ERR("Expected option -c"); rc = tool_rc_option_error; } if (ctx.contextpath && ctx.cp_hash_path) { LOG_ERR("Cannot output contextpath when calculating cp_hash"); rc = tool_rc_option_error; } return rc; } static tool_rc init(ESYS_CONTEXT *ectx) { bool res = files_load_public(ctx.object.pubpath, &ctx.object.public); if (!res) { return tool_rc_general_error; } res = files_load_private(ctx.object.privpath, &ctx.object.private); if (!res) { return tool_rc_general_error; } return tpm2_util_object_load_auth(ectx, ctx.parent.ctx_path, ctx.parent.auth_str, &ctx.parent.object, false, TPM2_HANDLE_ALL_W_NV); } static tool_rc finish(ESYS_CONTEXT *ectx) { TPM2B_NAME *name; tool_rc rc = tpm2_tr_get_name(ectx, ctx.object.handle, &name); if (rc != tool_rc_success) { return rc; } if (ctx.namepath) { bool result = files_save_bytes_to_file(ctx.namepath, name->name, name->size); free(name); if (!result) { return tool_rc_general_error; } } else { tpm2_tool_output("name: "); tpm2_util_print_tpm2b(name); tpm2_tool_output("\n"); free(name); } return files_save_tpm_context_to_path(ectx, ctx.object.handle, ctx.contextpath); } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = check_opts(); if (rc != tool_rc_success) { return rc; } rc = init(ectx); if (rc != tool_rc_success) { return rc; } if (!ctx.cp_hash_path) { rc = tpm2_load(ectx, &ctx.parent.object, &ctx.object.private, &ctx.object.public, &ctx.object.handle, NULL); if (rc != tool_rc_success) { return rc; } return finish(ectx); } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_load(ectx, &ctx.parent.object, &ctx.object.private, &ctx.object.public, &ctx.object.handle, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.parent.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("load", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_loadexternal.c000066400000000000000000000250701412464516500203440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_auth_util.h" #include "tpm2_hierarchy.h" #include "tpm2_openssl.h" #include "tpm2_tool.h" #define BASE_DEFAULT_ATTRS \ (TPMA_OBJECT_DECRYPT | TPMA_OBJECT_SIGN_ENCRYPT | TPMA_OBJECT_USERWITHAUTH) #define DEFAULT_NAME_ALG TPM2_ALG_SHA256 typedef struct tpm_loadexternal_ctx tpm_loadexternal_ctx; struct tpm_loadexternal_ctx { char *context_file_path; TPMI_RH_HIERARCHY hierarchy_value; ESYS_TR handle; char *public_key_path; /* path to the public portion of an object */ char *private_key_path; /* path to the private portion of an object */ char *attrs; /* The attributes to use */ char *auth; /* The password for use of the private portion */ char *policy; /* a policy for use of the private portion */ char *name_alg; /* name hashing algorithm */ char *key_type; /* type of key attempting to load, defaults to an auto attempt */ char *name_path; /* An optional path to output the loaded objects name information to */ char *passin; /* an optional auth string for the input key file for OSSL */ }; static tpm_loadexternal_ctx ctx = { /* * default to the NULL hierarchy, as the tpm rejects loading a private * portion of an object in other hierarchies. */ .hierarchy_value = TPM2_RH_NULL, }; static tool_rc load_external(ESYS_CONTEXT *ectx, TPM2B_PUBLIC *pub, TPM2B_SENSITIVE *priv, bool has_priv, TPM2B_NAME **name) { uint32_t hierarchy; TSS2_RC rval = fix_esys_hierarchy(ctx.hierarchy_value, &hierarchy); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Unknown hierarchy"); return tool_rc_from_tpm(rval); } tool_rc rc = tpm2_loadexternal(ectx, has_priv ? priv : NULL, pub, hierarchy, &ctx.handle); if (rc != tool_rc_success) { return rc; } return tpm2_tr_get_name(ectx, ctx.handle, name); } static void setup_default_attrs(TPMA_OBJECT *attrs, bool has_policy, bool has_auth) { /* Handle Default Setup */ *attrs = BASE_DEFAULT_ATTRS; if (has_policy && !has_auth) { *attrs &= ~TPMA_OBJECT_USERWITHAUTH; } } static bool on_option(char key, char *value) { bool result; switch (key) { case 'C': result = tpm2_util_handle_from_optarg(value, &ctx.hierarchy_value, TPM2_HANDLE_FLAGS_ALL_HIERACHIES); if (!result) { return false; } break; case 'u': ctx.public_key_path = value; break; case 'r': ctx.private_key_path = value; break; case 'c': ctx.context_file_path = value; break; case 'a': ctx.attrs = value; break; case 'p': ctx.auth = value; break; case 'L': ctx.policy = value; break; case 'g': ctx.name_alg = value; break; case 'G': ctx.key_type = value; break; case 'n': ctx.name_path = value; break; case 0: ctx.passin = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C'}, { "public", required_argument, NULL, 'u'}, { "private", required_argument, NULL, 'r'}, { "key-context", required_argument, NULL, 'c'}, { "attributes", required_argument, NULL, 'a'}, { "policy", required_argument, NULL, 'L'}, { "auth", required_argument, NULL, 'p'}, { "hash-algorithm", required_argument, NULL, 'g'}, { "key-algorithm", required_argument, NULL, 'G'}, { "name", required_argument, NULL, 'n'}, { "passin", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:u:r:c:a:p:L:g:G:n:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (!ctx.public_key_path && !ctx.private_key_path) { LOG_ERR("Expected either -r or -u options"); return tool_rc_option_error; } if (!ctx.context_file_path) { LOG_ERR("Expected -c option"); return tool_rc_option_error; } /* * We only load a TSS format for the public portion, so if * someone hands us a public file, we'll assume the TSS format when * no -G is specified. * * If they specify a private they need to tell us the type we expect. * This helps reduce auto-guess complexity, as well as future proofing * us for being able to load XOR. Ie we don't want to guess XOR or HMAC * in leui of AES or vice versa. */ if (!ctx.key_type && ctx.private_key_path) { LOG_ERR("Expected key type via -G option when specifying private" " portion of object"); return tool_rc_option_error; } TPMA_OBJECT def_attrs = 0; if (!ctx.attrs) { setup_default_attrs(&def_attrs, !!ctx.policy, !!ctx.auth); } /* * Set the AUTH value for sensitive portion */ TPM2B_SENSITIVE priv = { 0 }; /* * Load the users specified public object if specified via -u */ TPM2B_PUBLIC pub = { 0 }; /* * Input values are public assumed to be in the TSS format unless: * 1. A private (TPM2B_PRIVATE) key is specified. Since a TPM2B_PRIVATE is nonsense to load externally. * 2. The key_type is specified indicated you want to load an external public raw key of some type * 3. The third option is no public, which means the public could be coming from a private PEM file * */ if (!ctx.key_type && ctx.public_key_path) { /* Load TSS */ bool result = files_load_public(ctx.public_key_path, &pub); if (!result) { return tool_rc_general_error; } /* overwrite certain things here */ if (ctx.name_alg) { pub.publicArea.nameAlg = tpm2_alg_util_from_optarg(ctx.name_alg, tpm2_alg_util_flags_hash); if (pub.publicArea.nameAlg == TPM2_ALG_ERROR) { LOG_ERR("Invalid name hashing algorithm, got\"%s\"", ctx.name_alg); return tool_rc_unsupported; } } if (ctx.attrs) { bool res = tpm2_attr_util_obj_from_optarg(ctx.attrs, &pub.publicArea.objectAttributes); if (!res) { return tool_rc_unsupported; } } if (ctx.policy) { pub.publicArea.authPolicy.size = sizeof(pub.publicArea.authPolicy.buffer); bool res = files_load_bytes_from_path(ctx.policy, pub.publicArea.authPolicy.buffer, &pub.publicArea.authPolicy.size); if (!res) { return tool_rc_general_error; } } } else if (ctx.public_key_path || ctx.key_type) { /* Load RAW public */ TPM2B_PUBLIC template = { 0 }; tool_rc rc = tpm2_alg_util_public_init(ctx.key_type, ctx.name_alg, ctx.attrs, ctx.policy, def_attrs, &template); if (rc != tool_rc_success) { return rc; } pub = template; if (ctx.public_key_path) { /* Get the public from a RAW source, ie PEM */ bool result = tpm2_openssl_load_public(ctx.public_key_path, template.publicArea.type, &pub); if (!result) { return tool_rc_general_error; } } } else { LOG_ERR("Unkown internal state"); return tool_rc_general_error; } /* * Okay, we have the public portion in some form, at a minimum a template and at a maximum a fully specified * public, load the private portion. */ if (ctx.private_key_path) { /* * when nameAlg is not TPM2_ALG_NULL, seed value is needed to pass * consistency checks by TPM */ TPM2B_DIGEST *seed = &priv.sensitiveArea.seedValue; seed->size = tpm2_alg_util_get_hash_size(pub.publicArea.nameAlg); if (seed->size != 0) { RAND_bytes(seed->buffer, seed->size); } tpm2_openssl_load_rc load_status = tpm2_openssl_load_private( ctx.private_key_path, ctx.passin, ctx.auth, &pub, &pub, &priv); if (load_status == lprc_error) { return tool_rc_general_error; } /* * If we cannot load the public from the private and a path * is not specified for public, this is an error. * * If we loaded the public from the private and a public was * specified, this is warning. re-init public and load the * specified one. */ if (!tpm2_openssl_did_load_public(load_status) && !ctx.public_key_path) { LOG_ERR("Only loaded a private key, expected public key in either" " private PEM or -r option"); return tool_rc_general_error; } else if (tpm2_openssl_did_load_public(load_status) && ctx.public_key_path) { /* Okay... we got two publics, use the user specified one and issue a warning */ LOG_WARN("Loaded a public key from the private portion" " and a public portion was specified via -u. Defaulting" " to specified public"); /* * This effectively turns off cryptographic binding between * public and private portions of the object. Since we got a public portion * from the */ pub.publicArea.nameAlg = TPM2_ALG_NULL; } } TPM2B_NAME *name = NULL; tool_rc rc = load_external(ectx, &pub, &priv, ctx.private_key_path != NULL, &name); if (rc != tool_rc_success) { goto out; } assert(name); rc = files_save_tpm_context_to_path(ectx, ctx.handle, ctx.context_file_path); if (rc != tool_rc_success) { goto out; } tpm2_tool_output("name: "); tpm2_util_hexdump(name->name, name->size); tpm2_tool_output("\n"); if (ctx.name_path) { bool result = files_save_bytes_to_file(ctx.name_path, name->name, name->size); if (!result) { rc = tool_rc_general_error; goto out; } } out: free(name); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("loadexternal", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_makecredential.c000066400000000000000000000303611412464516500206310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_identity_util.h" #include "tpm2_options.h" #include "tpm2_openssl.h" typedef struct tpm_makecred_ctx tpm_makecred_ctx; struct tpm_makecred_ctx { TPM2B_NAME object_name; char *out_file_path; char *input_secret_data; char *public_key_path; /* path to the public portion of an object */ TPM2B_PUBLIC public; TPM2B_DIGEST credential; struct { UINT8 e :1; UINT8 s :1; UINT8 n :1; UINT8 o :1; } flags; char *key_type; //type of key attempting to load, defaults to auto attempt }; static tpm_makecred_ctx ctx = { .object_name = TPM2B_EMPTY_INIT, .public = TPM2B_EMPTY_INIT, .credential = TPM2B_EMPTY_INIT, }; static bool write_cred_and_secret(const char *path, TPM2B_ID_OBJECT *cred, TPM2B_ENCRYPTED_SECRET *secret) { bool result = false; FILE *fp = fopen(path, "wb+"); if (!fp) { LOG_ERR("Could not open file \"%s\" error: \"%s\"", path, strerror(errno)); return false; } result = files_write_header(fp, 1); if (!result) { LOG_ERR("Could not write version header"); goto out; } result = files_write_16(fp, cred->size); if (!result) { LOG_ERR("Could not write credential size"); goto out; } result = files_write_bytes(fp, cred->credential, cred->size); if (!result) { LOG_ERR("Could not write credential data"); goto out; } result = files_write_16(fp, secret->size); if (!result) { LOG_ERR("Could not write secret size"); goto out; } result = files_write_bytes(fp, secret->secret, secret->size); if (!result) { LOG_ERR("Could not write secret data"); goto out; } result = true; out: fclose(fp); return result; } static tool_rc make_external_credential_and_save(void) { /* * Get name_alg from the public key */ TPMI_ALG_HASH name_alg = ctx.public.publicArea.nameAlg; /* * Generate and encrypt seed */ TPM2B_DIGEST seed = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer); TPM2B_ENCRYPTED_SECRET encrypted_seed = TPM2B_EMPTY_INIT; unsigned char label[10] = { 'I', 'D', 'E', 'N', 'T', 'I', 'T', 'Y', 0 }; bool res = tpm2_identity_util_share_secret_with_public_key(&seed, &ctx.public, label, 9, &encrypted_seed); if (!res) { LOG_ERR("Failed Seed Encryption\n"); return tool_rc_general_error; } /* * Perform identity structure calculations (off of the TPM) */ TPM2B_MAX_BUFFER hmac_key; TPM2B_MAX_BUFFER enc_key; tpm2_identity_util_calc_outer_integrity_hmac_key_and_dupsensitive_enc_key( &ctx.public, &ctx.object_name, &seed, &hmac_key, &enc_key); /* * The ctx.credential needs to be marshalled into struct with * both size and contents together (to be encrypted as a block) */ TPM2B_MAX_BUFFER marshalled_inner_integrity = TPM2B_EMPTY_INIT; marshalled_inner_integrity.size = ctx.credential.size + sizeof(ctx.credential.size); UINT16 cred_size = ctx.credential.size; if (!tpm2_util_is_big_endian()) { cred_size = tpm2_util_endian_swap_16(cred_size); } memcpy(marshalled_inner_integrity.buffer, &cred_size, sizeof(cred_size)); memcpy(&marshalled_inner_integrity.buffer[2], ctx.credential.buffer, ctx.credential.size); /* * Perform inner encryption (encIdentity) and outer HMAC (outerHMAC) */ TPM2B_DIGEST outer_hmac = TPM2B_EMPTY_INIT; TPM2B_MAX_BUFFER encrypted_sensitive = TPM2B_EMPTY_INIT; tpm2_identity_util_calculate_outer_integrity(name_alg, &ctx.object_name, &marshalled_inner_integrity, &hmac_key, &enc_key, &ctx.public.publicArea.parameters.rsaDetail.symmetric, &encrypted_sensitive, &outer_hmac); /* * Package up the info to save * cred_bloc = outer_hmac || encrypted_sensitive * secret = encrypted_seed (with pubEK) */ TPM2B_ID_OBJECT cred_blob = TPM2B_TYPE_INIT(TPM2B_ID_OBJECT, credential); UINT16 outer_hmac_size = outer_hmac.size; if (!tpm2_util_is_big_endian()) { outer_hmac_size = tpm2_util_endian_swap_16(outer_hmac_size); } int offset = 0; memcpy(cred_blob.credential + offset, &outer_hmac_size, sizeof(outer_hmac.size)); offset += sizeof(outer_hmac.size); memcpy(cred_blob.credential + offset, outer_hmac.buffer, outer_hmac.size); offset += outer_hmac.size; //NOTE: do NOT include the encrypted_sensitive size, since it is encrypted with the blob! memcpy(cred_blob.credential + offset, encrypted_sensitive.buffer, encrypted_sensitive.size); cred_blob.size = outer_hmac.size + encrypted_sensitive.size + sizeof(outer_hmac.size); return write_cred_and_secret(ctx.out_file_path, &cred_blob, &encrypted_seed) ? tool_rc_success : tool_rc_general_error; } static tool_rc make_credential_and_save(ESYS_CONTEXT *ectx) { TPM2B_ID_OBJECT *cred_blob; TPM2B_ENCRYPTED_SECRET *secret; ESYS_TR tr_handle = ESYS_TR_NONE; tool_rc rc = tpm2_loadexternal(ectx, NULL, &ctx.public, TPM2_RH_NULL, &tr_handle); if (rc != tool_rc_success) { return rc; } rc = tpm2_makecredential(ectx, tr_handle, &ctx.credential, &ctx.object_name, &cred_blob, &secret); if (rc != tool_rc_success) { return rc; } rc = tpm2_flush_context(ectx, tr_handle); if (rc != tool_rc_success) { free(cred_blob); free(secret); return rc; } bool ret = write_cred_and_secret(ctx.out_file_path, cred_blob, secret); free(cred_blob); free(secret); return ret ? tool_rc_success : tool_rc_general_error; } static bool on_option(char key, char *value) { switch (key) { case 'u': if (ctx.flags.e) { LOG_ERR("Specify public key with **-u** or **-e**, not both"); return false; } ctx.public_key_path = value; ctx.flags.e = 1; break; case 'e': if (ctx.flags.e) { LOG_ERR("Specify encryption key with **-u** or **-e**, not both"); return false; } ctx.public_key_path = value; ctx.flags.e = 1; break; case 's': ctx.input_secret_data = strcmp("-", value) ? value : NULL; ctx.flags.s = 1; break; case 'n': ctx.object_name.size = BUFFER_SIZE(TPM2B_NAME, name); int q; if ((q = tpm2_util_hex_to_byte_structure(value, &ctx.object_name.size, ctx.object_name.name)) != 0) { LOG_ERR("FAILED: %d", q); return false; } ctx.flags.n = 1; break; case 'o': ctx.out_file_path = value; ctx.flags.o = 1; break; case 'G': ctx.key_type = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { {"encryption-key", required_argument, NULL, 'e'}, {"public", required_argument, NULL, 'u'}, {"secret", required_argument, NULL, 's'}, {"name", required_argument, NULL, 'n'}, {"credential-blob", required_argument, NULL, 'o'}, { "key-algorithm", required_argument, NULL, 'G'}, }; *opts = tpm2_options_new("G:u:e:s:n:o:", ARRAY_LEN(topts), topts, on_option, NULL, TPM2_OPTIONS_OPTIONAL_SAPI); return *opts != NULL; } static void set_default_TCG_EK_template(TPMI_ALG_PUBLIC alg) { switch (alg) { case TPM2_ALG_RSA: ctx.public.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM2_ALG_AES; ctx.public.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; ctx.public.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM2_ALG_CFB; ctx.public.publicArea.parameters.rsaDetail.scheme.scheme = TPM2_ALG_NULL; ctx.public.publicArea.parameters.rsaDetail.keyBits = 2048; ctx.public.publicArea.parameters.rsaDetail.exponent = 0; ctx.public.publicArea.unique.rsa.size = 256; break; case TPM2_ALG_ECC: ctx.public.publicArea.parameters.eccDetail.symmetric.algorithm = TPM2_ALG_AES; ctx.public.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; ctx.public.publicArea.parameters.eccDetail.symmetric.mode.sym = TPM2_ALG_CFB; ctx.public.publicArea.parameters.eccDetail.scheme.scheme = TPM2_ALG_NULL; ctx.public.publicArea.parameters.eccDetail.curveID = TPM2_ECC_NIST_P256; ctx.public.publicArea.parameters.eccDetail.kdf.scheme = TPM2_ALG_NULL; ctx.public.publicArea.unique.ecc.x.size = 32; ctx.public.publicArea.unique.ecc.y.size = 32; break; } ctx.public.publicArea.objectAttributes = TPMA_OBJECT_RESTRICTED | TPMA_OBJECT_ADMINWITHPOLICY | TPMA_OBJECT_DECRYPT | TPMA_OBJECT_FIXEDTPM | TPMA_OBJECT_FIXEDPARENT | TPMA_OBJECT_SENSITIVEDATAORIGIN; static const TPM2B_DIGEST auth_policy = { .size = 32, .buffer = { 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 } }; TPM2B_DIGEST *authp = &ctx.public.publicArea.authPolicy; *authp = auth_policy; ctx.public.publicArea.nameAlg = TPM2_ALG_SHA256; } static tool_rc process_input(void) { TPMI_ALG_PUBLIC alg = TPM2_ALG_NULL; if (ctx.key_type) { LOG_WARN("Because **-G** is specified, assuming input encryption public key is in PEM format."); alg = tpm2_alg_util_from_optarg(ctx.key_type, tpm2_alg_util_flags_asymmetric); if (alg == TPM2_ALG_ERROR || (alg != TPM2_ALG_RSA && alg != TPM2_ALG_ECC)) { LOG_ERR("Unsupported key type, got: \"%s\"", ctx.key_type); return tool_rc_general_error; } } if (ctx.public_key_path) { bool result = alg != TPM2_ALG_NULL ? tpm2_openssl_load_public(ctx.public_key_path, alg, &ctx.public) : files_load_public(ctx.public_key_path, &ctx.public); if (!result) { return tool_rc_general_error; } } /* * Since it is a PEM we will fixate the key properties from TCG EK * template since we had to choose "a template". */ if (ctx.key_type) { set_default_TCG_EK_template(alg); } if (!ctx.flags.s) { LOG_ERR("Specify the secret either as a file or a '-' for stdin"); return tool_rc_option_error; } if (!ctx.flags.e || !ctx.flags.n || !ctx.flags.o) { LOG_ERR("Expected mandatory options e, n, o."); return tool_rc_option_error; } /* * Maximum size of the allowed secret-data size to fit in TPM2B_DIGEST */ ctx.credential.size = TPM2_SHA512_DIGEST_SIZE; bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_secret_data, &ctx.credential.size, ctx.credential.buffer); if (!result) { return tool_rc_general_error; } /* * If input was read from stdin, check if a larger data set was specified * and error out. */ if (ctx.credential.size > TPM2_SHA512_DIGEST_SIZE) { LOG_ERR("Size is larger than buffer, got %d expected less than or equal" "to %d", ctx.credential.size, TPM2_SHA512_DIGEST_SIZE); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = process_input(); if (rc != tool_rc_success) { return rc; } // Run it outside of a TPM return ectx ? make_credential_and_save(ectx) : make_external_credential_and_save(); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("makecredential", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_nvcertify.c000066400000000000000000000245411412464516500176750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm_nvcertify_ctx tpm_nvcertify_ctx; struct tpm_nvcertify_ctx { //Input struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } nvindex_authobj; TPM2_HANDLE nv_index; TPMI_ALG_HASH halg; TPMI_ALG_SIG_SCHEME sig_scheme; UINT16 size; UINT16 offset; const char *policy_qualifier_arg; //Output char *certify_info_path; char *signature_path; tpm2_convert_sig_fmt sig_format; char *cp_hash_path; }; static tpm_nvcertify_ctx ctx = { .halg = TPM2_ALG_NULL, .sig_scheme = TPM2_ALG_NULL, }; static bool set_digest_algorithm(char *value) { ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Could not convert to number or lookup algorithm, got: " "\"%s\"", value); return false; } return true; } static bool set_signing_scheme(char *value) { ctx.sig_scheme = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.sig_scheme == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } return true; } static bool set_signature_format(char *value) { ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } return true; } static bool on_option(char key, char *value) { bool result = true; uint32_t input_value; switch (key) { case 'C': ctx.signing_key.ctx_path = value; break; case 'P': ctx.signing_key.auth_str = value; break; case 'c': ctx.nvindex_authobj.ctx_path = value; break; case 'p': ctx.nvindex_authobj.auth_str = value; break; case 'g': result = set_digest_algorithm(value); goto on_option_out; case 's': result = set_signing_scheme(value); goto on_option_out; case 'f': result = set_signature_format(value); goto on_option_out; case 'o': ctx.signature_path = value; break; case 'q': ctx.policy_qualifier_arg = value; break; case 0: result = tpm2_util_string_to_uint32(value, &input_value); if (!result) { LOG_ERR("Could not convert size to number, got: \"%s\"", value); return false; } if (input_value > UINT16_MAX) { LOG_ERR("Specified size is larger than that allowed by command"); return false; } else { ctx.size = input_value; } break; case 1: result = tpm2_util_string_to_uint32(value, &input_value); if (!result) { LOG_ERR("Could not convert offset to number, got: \"%s\"", value); return false; } if (input_value > UINT16_MAX) { LOG_ERR("Specified offset is larger than that allowed by command"); return false; } else { ctx.offset = input_value; } break; case 2: ctx.certify_info_path = value; break; case 3: ctx.cp_hash_path = value; break; } on_option_out: return result; } static bool on_arg(int argc, char **argv) { /* * If the user doesn't specify an authorization hierarchy use the index */ if (!ctx.nvindex_authobj.ctx_path) { ctx.nvindex_authobj.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "signingkey-context", required_argument, NULL, 'C' }, { "signingkey-auth", required_argument, NULL, 'P' }, { "nvauthobj-context", required_argument, NULL, 'c' }, { "nvauthobj-auth", required_argument, NULL, 'p' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "scheme", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "signature", required_argument, NULL, 'o' }, { "qualification", required_argument, NULL, 'q' }, { "size", required_argument, NULL, 0 }, { "offset", required_argument, NULL, 1 }, { "attestation", required_argument, NULL, 2 }, { "cphash", required_argument, NULL, 3 }, }; *opts = tpm2_options_new("C:P:c:p:g:s:f:o:q:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static bool is_input_options_args_valid(ESYS_CONTEXT *ectx) { if (!ctx.signing_key.ctx_path) { LOG_ERR("Must specify the signing key '-C'."); return false; } if (!ctx.signature_path) { LOG_ERR("Must specify the file path to save signature '-o'"); return false; } if (!ctx.certify_info_path) { LOG_ERR("Must specify file path to save attestation '--attestation'"); return false; } /* * Ensure that NV index is large enough for certifying data size at offset. */ bool result = true; TPM2B_NV_PUBLIC *nv_public = NULL; tool_rc rc = tpm2_util_nv_read_public(ectx, ctx.nv_index, &nv_public); if (rc != tool_rc_success) { LOG_ERR("Failed to access NVRAM public area at index 0x%X", ctx.nv_index); result = false; goto is_input_options_args_valid_out; } if (ctx.offset + ctx.size > nv_public->nvPublic.dataSize) { LOG_ERR("Size to read at offset is bigger than nv index size"); result = false; goto is_input_options_args_valid_out; } is_input_options_args_valid_out: free(nv_public); return result; } static tool_rc process_nvcertify_input(ESYS_CONTEXT *ectx, TPMT_SIG_SCHEME *in_scheme, TPM2B_DATA *policy_qualifier) { /* * Load signing key and auth */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid signing key/ authorization."); return rc; } /* * Load NV index authorization object and auth */ rc = tpm2_util_object_load_auth(ectx, ctx.nvindex_authobj.ctx_path, ctx.nvindex_authobj.auth_str, &ctx.nvindex_authobj.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid object specified for NV index authorization."); return rc; } /* * Set appropriate signature scheme for key type */ rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.signing_key.object.tr_handle, &ctx.halg, ctx.sig_scheme, in_scheme); if (rc != tool_rc_success) { LOG_ERR("bad signature scheme for key type!"); return rc; } /* * Qualifier data is optional. If not specified default to 0 */ if (ctx.policy_qualifier_arg) { policy_qualifier->size = sizeof(policy_qualifier->buffer); bool result = tpm2_util_bin_from_hex_or_file(ctx.policy_qualifier_arg, &policy_qualifier->size, policy_qualifier->buffer); if (!result) { return tool_rc_general_error; } } return tool_rc_success; } static tool_rc process_nvcertify_output(TPMT_SIGNATURE *signature, TPM2B_ATTEST *certify_info) { bool result = tpm2_convert_sig_save(signature, ctx.sig_format, ctx.signature_path); if (!result) { LOG_ERR("Failed saving signature data."); return tool_rc_general_error; } result = files_save_bytes_to_file(ctx.certify_info_path, certify_info->attestationData, certify_info->size); if (!result) { LOG_ERR("Failed saving attestation data."); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { /* opts is unused, avoid compiler warning */ UNUSED(flags); bool result = is_input_options_args_valid(ectx); if (!result) { return tool_rc_option_error; } //Input TPMT_SIG_SCHEME in_scheme; TPM2B_DATA policy_qualifier = TPM2B_EMPTY_INIT; tool_rc rc = process_nvcertify_input(ectx, &in_scheme, &policy_qualifier); if (rc != tool_rc_success) { return rc; } //ESAPI call TPMT_SIGNATURE *signature = NULL; TPM2B_ATTEST *certify_info = NULL; if (!ctx.cp_hash_path) { rc = tpm2_nvcertify(ectx, &ctx.signing_key.object, &ctx.nvindex_authobj.object, ctx.nv_index, ctx.offset, ctx.size, &in_scheme, &certify_info, &signature, &policy_qualifier, NULL); if (rc != tool_rc_success) { goto tpm2_tool_onrun_out; } //Output rc = process_nvcertify_output(signature, certify_info); goto tpm2_tool_onrun_out; } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_nvcertify(ectx, &ctx.signing_key.object, &ctx.nvindex_authobj.object, ctx.nv_index, ctx.offset, ctx.size, &in_scheme, &certify_info, &signature, &policy_qualifier, &cp_hash); if (rc != tool_rc_success) { return rc; } result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } tpm2_tool_onrun_out: Esys_Free(signature); Esys_Free(certify_info); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tool_rc_success; if (!ctx.cp_hash_path) { tool_rc tmp_rc = tpm2_session_close(&ctx.signing_key.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } tmp_rc = tpm2_session_close(&ctx.nvindex_authobj.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvcertify", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvdefine.c000066400000000000000000000344311412464516500174610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_auth_util.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #include "tpm2_tool.h" typedef struct tpm_nvdefine_ctx tpm_nvdefine_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 struct tpm_nvdefine_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPMI_RH_NV_INDEX nv_index; bool size_set; UINT16 size; TPMA_NV nv_attribute; TPM2B_AUTH nv_auth; TPMI_ALG_HASH halg; char *policy_file; char *index_auth_str; TPM2B_NV_PUBLIC public_info; /* * Outputs */ /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_nvdefine_ctx ctx = { .auth_hierarchy = { .ctx_path = "o", }, .nv_auth = TPM2B_EMPTY_INIT, .halg = TPM2_ALG_SHA256, .public_info = TPM2B_EMPTY_INIT, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; static tool_rc nv_space_define(ESYS_CONTEXT *ectx) { tool_rc rc = tpm2_nv_definespace(ectx, &ctx.auth_hierarchy.object, &ctx.nv_auth, &ctx.public_info, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); if (rc != tool_rc_success) { if (ctx.is_command_dispatch) { LOG_ERR("Failed to create NV index 0x%x.", ctx.nv_index); } return rc; } if (ctx.is_command_dispatch) { tpm2_tool_output("nv-index: 0x%x\n", ctx.nv_index); } return rc; } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static void handle_default_attributes(void) { /* attributes set no need for defaults */ if (ctx.nv_attribute) { return; } ESYS_TR h = ctx.auth_hierarchy.object.tr_handle; if (h == ESYS_TR_RH_OWNER) { ctx.nv_attribute |= TPMA_NV_OWNERWRITE | TPMA_NV_OWNERREAD; } else if (h == ESYS_TR_RH_PLATFORM) { ctx.nv_attribute |= TPMA_NV_PPWRITE | TPMA_NV_PPREAD; } /* else it's an nv index for auth */ /* if it has a policy file, set policy read and write vs auth read and write */ if (ctx.policy_file) { ctx.nv_attribute |= TPMA_NV_POLICYWRITE | TPMA_NV_POLICYREAD; } else { ctx.nv_attribute |= TPMA_NV_AUTHWRITE | TPMA_NV_AUTHREAD; } } static tool_rc handle_no_index_specified(ESYS_CONTEXT *ectx, TPM2_NV_INDEX *chosen) { /* get the max NV index for the TPM */ TPMS_CAPABILITY_DATA *capabilities = NULL; tool_rc rc = tpm2_getcap(ectx, TPM2_CAP_TPM_PROPERTIES, TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES, NULL, &capabilities); if (rc != tool_rc_success) { return rc; } TPMS_TAGGED_PROPERTY *properties = capabilities->data.tpmProperties.tpmProperty; UINT32 count = capabilities->data.tpmProperties.count; if (!count) { LOG_ERR("Could not get maximum NV index, try specifying an NV index"); rc = tool_rc_general_error; goto out; } TPM2_NV_INDEX max = 0; UINT32 i; for (i=0; i < count; i++) { if (properties[i].property == TPM2_PT_NV_INDEX_MAX) { max = TPM2_HR_NV_INDEX | properties[i].value; } } if (!max) { LOG_ERR("Could not find max NV indices in capabilities"); rc = tool_rc_general_error; goto out; } /* done getting max NV index */ free(capabilities); capabilities = NULL; /* now find what NV indexes are in use */ rc = tpm2_getcap(ectx, TPM2_CAP_HANDLES, tpm2_util_hton_32(TPM2_HT_NV_INDEX), TPM2_PT_NV_INDEX_MAX, NULL, &capabilities); if (rc != tool_rc_success) { goto out; } /* * now starting at the first valid index, find one not in use * The TPM interface makes no guarantee that handles are returned in order * so we have to do a linear search every attempt for a free handle :-( */ bool found = false; TPM2_NV_INDEX choose; for (choose = TPM2_HR_NV_INDEX; choose < max; choose++) { /* take the index to guess and check against everything in use */ bool in_use = false; for (i = 0; i < capabilities->data.handles.count; i++) { TPMI_RH_NV_INDEX index = capabilities->data.handles.handle[i]; if (index == choose) { in_use = true; break; } } if (!in_use) { /* it's not in use, use the current value of choose */ found = true; break; } } if (!found) { LOG_ERR("No free NV index found"); rc = tool_rc_general_error; goto out; } *chosen = choose; out: free(capabilities); return rc; } static tool_rc validate_size(ESYS_CONTEXT *ectx) { UINT16 hash_size = tpm2_alg_util_get_hash_size(ctx.halg); switch ((ctx.nv_attribute & TPMA_NV_TPM2_NT_MASK) >> TPMA_NV_TPM2_NT_SHIFT) { case TPM2_NT_ORDINARY: if (!ctx.size_set) { ctx.size = tpm2_nv_util_max_allowed_nv_size(ectx, true); } break; case TPM2_NT_COUNTER: case TPM2_NT_BITS: case TPM2_NT_PIN_FAIL: case TPM2_NT_PIN_PASS: if (!ctx.size_set) { ctx.size = 8; } else if (ctx.size != 8) { LOG_ERR("Size is invalid for an NV index type," " it must be size of 8"); return tool_rc_general_error; } break; case TPM2_NT_EXTEND: if (!ctx.size_set) { ctx.size = hash_size; } else if (ctx.size != hash_size) { LOG_ERR("Size is invalid for an NV index type: \"extend\"," " it must match the name hash algorithm size of %" PRIu16, hash_size); return tool_rc_general_error; } break; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ tpm2_session *tmp; tool_rc rc = tpm2_auth_util_from_optarg(NULL, ctx.index_auth_str, &tmp, true); if (rc != tool_rc_success) { LOG_ERR("Invalid index authorization"); return rc; } const TPM2B_AUTH *auth = tpm2_session_get_auth_value(tmp); ctx.nv_auth = *auth; tpm2_session_close(&tmp); /* * 1.b Add object names and their auth sessions */ rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid authorization"); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ handle_default_attributes(); if (!ctx.nv_index) { rc = handle_no_index_specified(ectx, &ctx.nv_index); if (rc != tool_rc_success) { return rc; } } rc = validate_size(ectx); if (rc != tool_rc_success) { return rc; } ctx.public_info.nvPublic.nvIndex = ctx.nv_index; ctx.public_info.nvPublic.nameAlg = ctx.halg; ctx.public_info.nvPublic.attributes = ctx.nv_attribute; ctx.public_info.nvPublic.dataSize = ctx.size; if (ctx.policy_file) { ctx.public_info.nvPublic.authPolicy.size = BUFFER_SIZE(TPM2B_DIGEST, buffer); bool is_policy_load = files_load_bytes_from_path(ctx.policy_file, ctx.public_info.nvPublic.authPolicy.buffer, &ctx.public_info.nvPublic.authPolicy.size); if (!is_policy_load) { return tool_rc_general_error; } } /* * 4. Configuration for calculating the pHash */ /* 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_hierarchy.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static tool_rc check_options(void) { if (!ctx.size && ctx.size_set) { LOG_WARN("Defining an index with size 0"); } /* * Todo: Add error checking for NV indices reserved for specific hierarchies */ return tool_rc_success; } static bool on_option(char key, char *value) { bool result; switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 's': ctx.size_set = true; result = tpm2_util_string_to_uint16(value, &ctx.size); if (!result) { LOG_ERR("Could not convert size to number, got: \"%s\"", value); return false; } break; case 'a': result = tpm2_util_string_to_uint32(value, &ctx.nv_attribute); if (!result) { result = tpm2_attr_util_nv_strtoattr(value, &ctx.nv_attribute); if (!result) { LOG_ERR( "Could not convert NV attribute to number or keyword, got: \"%s\"", value); return false; } } break; case 'p': ctx.index_auth_str = value; break; case 'L': ctx.policy_file = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { return false; } break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Invalid choice for name digest hash algorithm"); return false; } break; } return true; } static bool on_arg(int argc, char **argv) { return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "size", required_argument, NULL, 's' }, { "attributes", required_argument, NULL, 'a' }, { "hierarchy-auth", required_argument, NULL, 'P' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "index-auth", required_argument, NULL, 'p' }, { "policy", required_argument, NULL, 'L' }, { "cphash", required_argument, NULL, 0 }, {"rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:C:s:a:P:p:L:g:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = nv_space_define(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvdefine", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvextend.c000066400000000000000000000213441412464516500175150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" typedef struct tpm_nvextend_ctx tpm_nvextend_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 struct tpm_nvextend_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; const char *input_path; TPM2_HANDLE nv_index; TPM2B_NAME precalc_nvname; TPM2B_MAX_NV_BUFFER data; /* * Outputs */ /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; bool is_tcti_none; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_nvextend_ctx ctx = { .data.size = sizeof(ctx.data.buffer), .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; static tool_rc nvextend(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_nvextend(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &ctx.data, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, &ctx.precalc_nvname, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ tool_rc rc = (!ctx.is_tcti_none) ? tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV|TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P) : tpm2_util_handle_from_optarg(ctx.auth_hierarchy.ctx_path, &ctx.auth_hierarchy.object.handle, TPM2_HANDLE_FLAGS_NV|TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P) ? tool_rc_success : tool_rc_option_error; if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ ctx.input_path = strcmp(ctx.input_path, "-") ? ctx.input_path : NULL; bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_path, &ctx.data.size, ctx.data.buffer); if (!result) { return tool_rc_general_error; } /* * 4. Configuration for calculating the pHash */ /* 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_hierarchy.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * is_tcti_none [N] * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.is_tcti_none || (ctx.cp_hash_path && !ctx.rp_hash_path)) ? false : true; return rc; } static tool_rc check_options(tpm2_option_flags flags) { ctx.is_tcti_none = flags.tcti_none ? true : false; if (ctx.is_tcti_none && !ctx.cp_hash_path) { LOG_ERR("If tcti is none, then cpHash path must be specified"); return tool_rc_option_error; } bool is_nv_name_specified = ctx.precalc_nvname.size; if (ctx.is_tcti_none && !is_nv_name_specified) { LOG_ERR("Must specify the NVIndex name."); return tool_rc_option_error; } if (!ctx.is_tcti_none && is_nv_name_specified) { LOG_ERR("Do not specify NVIndex name, it is directly read from NV"); return tool_rc_option_error; } if (!ctx.input_path) { LOG_ERR("Must specify source of data to write to NV index"); return tool_rc_general_error; } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'i': ctx.input_path = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { return false; } break; case 'n': ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name); int q = tpm2_util_hex_to_byte_structure(value, &ctx.precalc_nvname.size, ctx.precalc_nvname.name); if (q) { LOG_ERR("FAILED: %d", q); return false; } break; } return true; } static bool on_arg(int argc, char **argv) { /* * If the user doesn't specify an authorization hierarchy use the index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "input", required_argument, NULL, 'i' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, { "name", required_argument, NULL, 'n' }, }; *opts = tpm2_options_new("S:C:P:i:n:", ARRAY_LEN(topts), topts, on_option, on_arg, TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(flags); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = nvextend(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ uint8_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); } if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvextend", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvincrement.c000066400000000000000000000054551412464516500202170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm_nvincrement_ctx tpm_nvincrement_ctx; struct tpm_nvincrement_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; char *cp_hash_path; }; static tpm_nvincrement_ctx ctx; static bool on_arg(int argc, char **argv) { /* If the user doesn't specify an authorization hierarchy use the index * passed to -x/--index for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } if (!ctx.cp_hash_path) { rc = tpm2_nv_increment(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, NULL); if (rc != tool_rc_success) { LOG_ERR("Failed to increment NV counter at index 0x%X", ctx.nv_index); } return rc; } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_nv_increment(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (!ctx.cp_hash_path) { return tpm2_session_close(&ctx.auth_hierarchy.object.session); } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvincrement", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvread.c000066400000000000000000000266451412464516500171520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 typedef struct tpm_nvread_ctx tpm_nvread_ctx; struct tpm_nvread_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; TPM2B_NAME precalc_nvname; UINT32 size_to_read; UINT32 offset; /* * Outputs */ char *output_file; UINT8* data_buffer; UINT16 bytes_written; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; bool is_tcti_none; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_nvread_ctx ctx = { .parameter_hash_algorithm = TPM2_ALG_ERROR, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc nv_read(ESYS_CONTEXT *ectx) { return tpm2_util_nv_read(ectx, ctx.nv_index, ctx.size_to_read, ctx.offset, &ctx.auth_hierarchy.object, &ctx.data_buffer, &ctx.bytes_written, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, &ctx.precalc_nvname, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc process_output(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ /* dump ctx.data_buffer to output file, if specified */ tool_rc rc = tool_rc_success; if (ctx.output_file) { if (!files_save_bytes_to_file(ctx.output_file, ctx.data_buffer, ctx.bytes_written)) { rc = tool_rc_general_error; goto out; } /* else use stdout if quiet is not specified */ } else if (!flags.quiet) { if (!files_write_bytes(stdout, ctx.data_buffer, ctx.bytes_written)) { rc = tool_rc_general_error; goto out; } } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); rc = is_file_op_success ? tool_rc_success : tool_rc_general_error; } out: return rc; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ /* Object #1 */ /* * When tcti is none AND only calculating cpHash only load the object * strings to calculate the names. */ tool_rc rc = (!ctx.is_tcti_none) ? tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P) : tpm2_util_handle_from_optarg(ctx.auth_hierarchy.ctx_path, &ctx.auth_hierarchy.object.handle, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P) ? tool_rc_success : tool_rc_option_error; if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization."); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_hierarchy.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); return rc; } static tool_rc check_options(tpm2_option_flags flags) { ctx.is_tcti_none = flags.tcti_none ? true : false; if (ctx.is_tcti_none && !ctx.cp_hash_path) { LOG_ERR("If tcti is none, then cpHash path must be specified"); return tool_rc_option_error; } /* * Peculiar to this and some other tools, the object (nvindex) name must * be specified when only calculating the cpHash. * * This breaks the compatibility with the 4.X tools where in a real tcti * is invoked to get a sapi handle to retrieve the params. Also this would * imply that a real NV index ought to be defined even in the case of simply * calculating the cpHash. * * To solve this conundrum, we can only mandate the requirement for the NV * index name in case tcti is specified as none. If tcti is not specified as * none we fall back to the old behavior of reading from a define NV index * * Also, tcti is setup to a fake_tcti when tcti is specified "none" as the * tool option affords TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI. * * If NVindex name is not specified and tcti is not none, it is expected * that the NV index is actually define. This behavior complies with the * backwards compatibility with 4.X */ bool is_nv_name_specified = ctx.precalc_nvname.size; if (ctx.is_tcti_none && !is_nv_name_specified) { LOG_ERR("Must specify the NVIndex name."); return tool_rc_option_error; } if (!ctx.is_tcti_none && is_nv_name_specified) { LOG_ERR("Do not specify NVIndex name, it is directly read from NV"); return tool_rc_option_error; } /* * 4.b Determine if TPM2_CC_ is to be dispatched * is_tcti_none [N] * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.is_tcti_none || (ctx.cp_hash_path && !ctx.rp_hash_path)) ? false : true; if (!ctx.size_to_read) { if(ctx.is_command_dispatch) { LOG_WARN("Reading full size of the NV index"); } else { LOG_ERR("Must specify the size to read."); return tool_rc_option_error; } } #define TYPICAL_NVACCESS_MAX 1024 #define TYPICAL_NVINDEX_MAX 2048 if (!ctx.is_command_dispatch) { if (ctx.size_to_read > TYPICAL_NVACCESS_MAX) { LOG_WARN("Calculating cpHash with NV access size larger than typical."); } if ((ctx.size_to_read + ctx.offset) > TYPICAL_NVINDEX_MAX) { LOG_WARN("Calculating cpHash with NV index size larger than typical"); } } return tool_rc_success; } static bool on_arg(int argc, char **argv) { /* * If the user doesn't specify an authorization hierarchy use the index * for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { bool result; switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'o': ctx.output_file = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 's': result = tpm2_util_string_to_uint32(value, &ctx.size_to_read); if (!result) { LOG_ERR("Could not convert size to number, got: \"%s\"", value); return false; } break; case 'n': ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name); int q = tpm2_util_hex_to_byte_structure(value, &ctx.precalc_nvname.size, ctx.precalc_nvname.name); if (q) { LOG_ERR("FAILED: %d", q); return false; } break; case 0: result = tpm2_util_string_to_uint32(value, &ctx.offset); if (!result) { LOG_ERR("Could not convert offset to number, got: \"%s\"", value); return false; } break; case 1: ctx.cp_hash_path = value; break; case 2: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "output", required_argument, NULL, 'o' }, { "size", required_argument, NULL, 's' }, { "offset", required_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, { "rphash", required_argument, NULL, 2 }, { "name", required_argument, NULL, 'n' }, { "auth", required_argument, NULL, 'P' }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("C:s:o:P:n:S:", ARRAY_LEN(topts), topts, on_option, on_arg, TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { /* * 1. Process options */ tool_rc rc = check_options(flags); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = nv_read(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx, flags); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ if (ctx.data_buffer) { free(ctx.data_buffer); } /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvread", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvreadlock.c000066400000000000000000000053331412464516500200120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" typedef struct tpm_nvreadlock_ctx tpm_nvreadlock_ctx; struct tpm_nvreadlock_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; char *cp_hash_path; }; static tpm_nvreadlock_ctx ctx; static bool on_arg(int argc, char **argv) { /* If the user doesn't specify an authorization hierarchy use the index * passed to -x/--index for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } if (!ctx.cp_hash_path) { return tpm2_nvreadlock(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, NULL); } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_nvreadlock(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (!ctx.cp_hash_path) { return tpm2_session_close(&ctx.auth_hierarchy.object.session); } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvreadlock", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvreadpublic.c000066400000000000000000000100211412464516500203260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "tpm2_alg_util.h" #include "tpm2_attr_util.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm2_nvreadpublic_ctx tpm2_nvreadpublic_ctx; struct tpm2_nvreadpublic_ctx { TPMI_RH_NV_INDEX nv_index; }; static tpm2_nvreadpublic_ctx ctx; static tool_rc print_nv_public(ESYS_CONTEXT *context, TPMI_RH_NV_INDEX index, TPM2B_NV_PUBLIC *nv_public) { ESYS_TR tr_handle = ESYS_TR_NONE; tool_rc rc = tpm2_tr_from_tpm_public(context, index, &tr_handle); if (rc != tool_rc_success) { return rc; } tpm2_tool_output("0x%x:\n", index); char *attrs = tpm2_attr_util_nv_attrtostr(nv_public->nvPublic.attributes); if (!attrs) { LOG_ERR("Could not convert attributes to string form"); } const char *alg = tpm2_alg_util_algtostr(nv_public->nvPublic.nameAlg, tpm2_alg_util_flags_hash); if (!alg) { LOG_ERR("Could not convert algorithm to string form"); } TPM2B_NAME *name = NULL; rc = tpm2_tr_get_name(context, tr_handle, &name); if (rc != tool_rc_success) { free(attrs); return rc; } tpm2_tool_output(" name: "); UINT16 i; for (i = 0; i < name->size; i++) { tpm2_tool_output("%02x", name->name[i]); } tpm2_tool_output("\n"); Esys_Free(name); tpm2_tool_output(" hash algorithm:\n"); tpm2_tool_output(" friendly: %s\n", alg); tpm2_tool_output(" value: 0x%X\n", nv_public->nvPublic.nameAlg); tpm2_tool_output(" attributes:\n"); tpm2_tool_output(" friendly: %s\n", attrs); tpm2_tool_output(" value: 0x%X\n", tpm2_util_ntoh_32(nv_public->nvPublic.attributes)); tpm2_tool_output(" size: %d\n", nv_public->nvPublic.dataSize); if (nv_public->nvPublic.authPolicy.size) { tpm2_tool_output(" authorization policy: "); UINT16 i; for (i = 0; i < nv_public->nvPublic.authPolicy.size; i++) { tpm2_tool_output("%02X", nv_public->nvPublic.authPolicy.buffer[i]); } tpm2_tool_output("\n"); } free(attrs); return tool_rc_success; } static tool_rc nv_readpublic(ESYS_CONTEXT *context) { TPMS_CAPABILITY_DATA *capability_data = NULL; if (ctx.nv_index == 0) { tool_rc rc = tpm2_getcap(context, TPM2_CAP_HANDLES, TPM2_HT_NV_INDEX << 24, TPM2_PT_NV_INDEX_MAX, NULL, &capability_data); if (rc != tool_rc_success) { return rc; } } else { capability_data = calloc(1, sizeof(*capability_data)); if (!capability_data) { LOG_ERR("oom"); return tool_rc_general_error; } capability_data->data.handles.count = 1; capability_data->data.handles.handle[0] = ctx.nv_index; } UINT32 i; for (i = 0; i < capability_data->data.handles.count; i++) { TPMI_RH_NV_INDEX index = capability_data->data.handles.handle[i]; TPM2B_NV_PUBLIC *nv_public; tool_rc rc = tpm2_util_nv_read_public(context, index, &nv_public); if (rc != tool_rc_success) { LOG_ERR("Failed to read the public part of NV index 0x%X", index); free(capability_data); return rc; } rc = print_nv_public(context, index, nv_public); free(nv_public); tpm2_tool_output("\n"); if (rc != tool_rc_success) { free(capability_data); return rc; } } free(capability_data); return tool_rc_success; } static bool on_arg(int argc, char **argv) { return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); return nv_readpublic(context); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvreadpublic", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_nvsetbits.c000066400000000000000000000212131412464516500176760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 typedef struct tpm_nvsetbits_ctx tpm_nvsetbits_ctx; struct tpm_nvsetbits_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; const char *bit_string; UINT64 bits; TPM2_HANDLE nv_index; TPM2B_NAME precalc_nvname; /* * Outputs */ /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; bool is_tcti_none; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_nvsetbits_ctx ctx = { .parameter_hash_algorithm = TPM2_ALG_ERROR, .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, }; static tool_rc nvsetbits(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_nvsetbits(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, ctx.bits, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, &ctx.precalc_nvname, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ /* Object #1 */ tool_rc rc = (!ctx.is_tcti_none) ? tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV|TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P) : tpm2_util_handle_from_optarg(ctx.auth_hierarchy.ctx_path, &ctx.auth_hierarchy.object.handle, TPM2_HANDLE_FLAGS_NV|TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P) ? tool_rc_success : tool_rc_option_error; if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations */ bool result = tpm2_util_string_to_uint64(ctx.bit_string, &ctx.bits); if (!result) { LOG_ERR("Could not convert option argument to number, got: \"%s\"", ctx.bit_string); return tool_rc_general_error; } /* * 4. Configuration for calculating the pHash */ /* * 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.auth_hierarchy.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * is_tcti_none [N] * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.is_tcti_none || (ctx.cp_hash_path && !ctx.rp_hash_path)) ? false : true; return rc; } static tool_rc check_options(tpm2_option_flags flags) { ctx.is_tcti_none = flags.tcti_none ? true : false; if (ctx.is_tcti_none && !ctx.cp_hash_path) { LOG_ERR("If tcti is none, then cpHash path must be specified"); return tool_rc_option_error; } bool is_nv_name_specified = ctx.precalc_nvname.size; if (ctx.is_tcti_none && !is_nv_name_specified) { LOG_ERR("Must specify the NVIndex name."); return tool_rc_option_error; } if (!ctx.is_tcti_none && is_nv_name_specified) { LOG_ERR("Do not specify NVIndex name, it is directly read from NV"); return tool_rc_option_error; } if (!ctx.bit_string) { LOG_ERR("Expected option --bits for specifying the bits to set"); return tool_rc_option_error; } return tool_rc_success; } static bool on_arg(int argc, char **argv) { if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'i': ctx.bit_string = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { LOG_ERR("Specify a max of 3 sessions"); return false; } break; case 'n': ctx.precalc_nvname.size = BUFFER_SIZE(TPM2B_NAME, name); int q = tpm2_util_hex_to_byte_structure(value, &ctx.precalc_nvname.size, ctx.precalc_nvname.name); if (q) { LOG_ERR("FAILED: %d", q); return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "bits", required_argument, NULL, 'i' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, { "name", required_argument, NULL, 'n' }, }; *opts = tpm2_options_new("C:P:i:S:n:", ARRAY_LEN(topts), topts, on_option, on_arg, TPM2_OPTIONS_OPTIONAL_SAPI_AND_FAKE_TCTI); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(flags); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = nvsetbits(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } /* * 3. Close auxiliary sessions */ size_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvsetbits", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvundefine.c000066400000000000000000000126431412464516500200250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" typedef struct tpm_nvundefine_ctx tpm_nvundefine_ctx; struct tpm_nvundefine_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; struct { const char *path; tpm2_session *session; } policy_session; struct { bool C; } flags; TPM2_HANDLE nv_index; char *cp_hash_path; }; static tpm_nvundefine_ctx ctx = { .auth_hierarchy.ctx_path = "owner", }; static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.flags.C = true; ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'S': ctx.policy_session.path = value; break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool on_arg(int argc, char **argv) { return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "session", required_argument, NULL, 'S' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:S:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * Read the public portion of the NV index so we can ascertain if * TPMA_NV_POLICYDELETE is set. This determines which command to use * to undefine the space. Either undefine or undefinespecial. */ TPM2B_NV_PUBLIC *nv_public = NULL; tool_rc rc = tpm2_util_nv_read_public(ectx, ctx.nv_index, &nv_public); if (rc != tool_rc_success) { LOG_ERR("Failed to read the public part of NV index 0x%X", ctx.nv_index); return rc; } bool has_policy_delete_set = !!(nv_public->nvPublic.attributes & TPMA_NV_POLICY_DELETE); Esys_Free(nv_public); /* * The default hierarchy is typically owner, however with a policy delete object it's always * the platform. */ if (!ctx.flags.C) { ctx.auth_hierarchy.ctx_path = has_policy_delete_set ? "platform" : "owner"; } /* now with the default sorted out, load the authorization object */ rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } bool result = true; TPM2B_DIGEST cp_hash = { .size = 0 }; /* has policy delete set, so do NV undefine special */ if (has_policy_delete_set) { if (!ctx.policy_session.path) { LOG_ERR("NV Spaces with attribute TPMA_NV_POLICY_DELETE require a" " policy session to be specified via \"-S\""); return tool_rc_general_error; } rc = tpm2_session_restore(ectx, ctx.policy_session.path, false, &ctx.policy_session.session); if (rc != tool_rc_success) { return rc; } /* * has to be an admin policy session for undefinespecial. * We can at least check that it is a session. */ TPM2_SE type = tpm2_session_get_type(ctx.policy_session.session); if (type != TPM2_SE_POLICY) { LOG_ERR("Expected a policy session when NV index has attribute" " TPMA_NV_POLICY_DELETE set."); return tool_rc_general_error; } if (!ctx.cp_hash_path) { return tpm2_nvundefinespecial(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, ctx.policy_session.session, NULL); } rc = tpm2_nvundefinespecial(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, ctx.policy_session.session, &cp_hash);; if (rc != tool_rc_success) { return rc; } goto nvundefine_out; } if (ctx.policy_session.path && !has_policy_delete_set) { LOG_WARN("Option -S is not required on NV indices that don't have" " attribute TPMA_NV_POLICY_DELETE set"); } if (!ctx.cp_hash_path) { return tpm2_nvundefine(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, NULL); } rc = tpm2_nvundefine(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &cp_hash);; if (rc != tool_rc_success) { return rc; } nvundefine_out: result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* attempt to close all sessions and report errors */ tool_rc rc = tool_rc_success; if (!ctx.cp_hash_path) { rc = tpm2_session_close(&ctx.policy_session.session); rc |= tpm2_session_close(&ctx.auth_hierarchy.object.session); } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvundefine", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvwrite.c000066400000000000000000000132411412464516500173550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm_nvwrite_ctx tpm_nvwrite_ctx; struct tpm_nvwrite_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; BYTE nv_buffer[TPM2_MAX_NV_BUFFER_SIZE]; FILE *input_file; UINT16 data_size; UINT16 offset; char *cp_hash_path; }; static tpm_nvwrite_ctx ctx = { .data_size = TPM2_MAX_NV_BUFFER_SIZE }; static bool is_input_options_args_valid(ESYS_CONTEXT *ectx) { if (ctx.cp_hash_path && ctx.data_size > TPM2_MAX_NV_BUFFER_SIZE) { LOG_ERR("Cannot calculat cpHash for buffers larger than NV max buffer"); return false; } if (!ctx.data_size) { LOG_WARN("Data to write is of size 0"); } /* * Ensure that writes will fit before attempting write to prevent data * from being partially written to the index. */ TPM2B_NV_PUBLIC *nv_public = NULL; tool_rc rc = tpm2_util_nv_read_public(ectx, ctx.nv_index, &nv_public); if (rc != tool_rc_success) { LOG_ERR("Failed to write NVRAM public area at index 0x%X", ctx.nv_index); free(nv_public); return false; } if (ctx.offset + ctx.data_size > nv_public->nvPublic.dataSize) { LOG_ERR("The starting offset (%u) and the size (%u) are larger than the" " defined space: %u.", ctx.offset, ctx.data_size, nv_public->nvPublic.dataSize); free(nv_public); return false; } free(nv_public); return true; } static tool_rc nv_write(ESYS_CONTEXT *ectx) { TPM2B_MAX_NV_BUFFER nv_write_data; UINT16 data_offset = 0; if (ctx.cp_hash_path) { nv_write_data.size = ctx.data_size; memcpy(nv_write_data.buffer, &ctx.nv_buffer, ctx.data_size); LOG_WARN("Calculating cpHash. Exiting without performing write."); TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_nvwrite(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &nv_write_data, ctx.offset, &cp_hash); if (rc != tool_rc_success) { LOG_ERR("CpHash calculation failed!"); return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } uint16_t max_data_size = tpm2_nv_util_max_allowed_nv_size(ectx, false); while (ctx.data_size > 0) { nv_write_data.size = ctx.data_size > max_data_size ? max_data_size : ctx.data_size; LOG_INFO("The data(size=%d) to be written:", nv_write_data.size); memcpy(nv_write_data.buffer, &ctx.nv_buffer[data_offset], nv_write_data.size); tool_rc rc = tpm2_nvwrite(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &nv_write_data, ctx.offset + data_offset, NULL); if (rc != tool_rc_success) { return rc; } ctx.data_size -= nv_write_data.size; data_offset += nv_write_data.size; } return tool_rc_success; } static bool on_option(char key, char *value) { char *input_file; switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'i': input_file = strcmp("-", value) ? value : NULL; return files_load_bytes_from_buffer_or_file_or_stdin(NULL, input_file, &ctx.data_size, ctx.nv_buffer); break; case 0: if (!tpm2_util_string_to_uint16(value, &ctx.offset)) { LOG_ERR("Could not convert starting offset, got: \"%s\"", value); return false; } break; case 1: ctx.cp_hash_path = value; break; } return true; } static bool on_arg(int argc, char **argv) { /* If the user doesn't specify an authorization hierarchy use the index * passed to -x/--index for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "input", required_argument, NULL, 'i' }, { "offset", required_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("C:P:i:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_options_args_valid(ectx); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } return nv_write(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvwrite", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_nvwritelock.c000066400000000000000000000065711412464516500202360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" typedef struct tpm_nvwritelock_ctx tpm_nvwritelock_ctx; struct tpm_nvwritelock_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; bool global_writelock; bool has_nv_argument; TPM2_HANDLE nv_index; char *cp_hash_path; }; static tpm_nvwritelock_ctx ctx; static bool on_arg(int argc, char **argv) { /* If the user doesn't specify an authorization hierarchy use the index * passed to -x/--index for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } ctx.has_nv_argument = true; return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 0: ctx.global_writelock= true; break; case 1: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "global", no_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tpm2_handle_flags valid_handles = TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P; if (!ctx.global_writelock) { valid_handles |= TPM2_HANDLE_FLAGS_NV; } else if (ctx.has_nv_argument) { LOG_ERR("Cannot specify nv index and --global flag"); return tool_rc_general_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, valid_handles); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } if (!ctx.cp_hash_path) { return ctx.global_writelock ? tpm2_nvglobalwritelock(ectx, &ctx.auth_hierarchy.object, NULL) : tpm2_nvwritelock(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, NULL); } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = ctx.global_writelock ? tpm2_nvglobalwritelock(ectx, &ctx.auth_hierarchy.object, &cp_hash) : tpm2_nvwritelock(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (!ctx.cp_hash_path) { return tpm2_session_close(&ctx.auth_hierarchy.object.session); } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("nvwritelock", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_pcrallocate.c000066400000000000000000000044451412464516500201560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" static struct { TPML_PCR_SELECTION pcr_selection; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; } ctx = { .pcr_selection = { .count = 2, .pcrSelections = { { .hash = TPM2_ALG_SHA1, .sizeofSelect = 3, .pcrSelect = { 0xff, 0xff, 0xff, } }, { .hash = TPM2_ALG_SHA256, .sizeofSelect = 3, .pcrSelect = { 0xff, 0xff, 0xff, } }, } }, .auth_hierarchy.ctx_path = "platform", }; static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Too many arguments"); return false; } if (argc == 1 && !pcr_parse_selections(argv[0], &ctx.pcr_selection)) { LOG_ERR("Could not parse pcr selections"); return false; } return true; } static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.auth_hierarchy.auth_str = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "auth", required_argument, NULL, 'P' }, }; *opts = tpm2_options_new("P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid platform authorization format."); return rc; } rc = tpm2_pcr_allocate(ectx, &ctx.auth_hierarchy.object, &ctx.pcr_selection); if (rc == tool_rc_success) { pcr_print_pcr_selections(&ctx.pcr_selection); } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth_hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("pcrallocate", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_pcrevent.c000066400000000000000000000164531412464516500175150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_hierarchy.h" #include "tpm2_auth_util.h" #include "tpm2_tool.h" typedef struct tpm_pcrevent_ctx tpm_pcrevent_ctx; struct tpm_pcrevent_ctx { struct { const char *auth_str; tpm2_session *session; } auth; ESYS_TR pcr; FILE *input; }; static tpm_pcrevent_ctx ctx = { .pcr = ESYS_TR_RH_NULL, }; static tool_rc tpm_pcrevent_file(ESYS_CONTEXT *ectx, TPML_DIGEST_VALUES **result) { unsigned long file_size = 0; FILE *input = ctx.input; /* Suppress error reporting with NULL path */ bool res = files_get_file_size(input, &file_size, NULL); /* If we can get the file size and its less than 1024, just do it in one hash invocation */ if (res && file_size <= BUFFER_SIZE(TPM2B_EVENT, buffer)) { TPM2B_EVENT buffer = TPM2B_INIT(file_size); res = files_read_bytes(ctx.input, buffer.buffer, buffer.size); if (!res) { LOG_ERR("Error reading input file!"); return tool_rc_general_error; } return tpm2_pcr_event(ectx, ctx.pcr, ctx.auth.session, &buffer, result); } ESYS_TR sequence_handle; TPM2B_AUTH null_auth = TPM2B_EMPTY_INIT; /* * Size is either unknown because the FILE * is a fifo, or it's too big * to do in a single hash call. Based on the size figure out the chunks * to loop over, if possible. This way we can call Complete with data. */ tool_rc rc = tpm2_hash_sequence_start(ectx, &null_auth, TPM2_ALG_NULL, &sequence_handle); if (rc != tool_rc_success) { return rc; } /* If we know the file size, we decrement the amount read and terminate the * loop when 1 block is left, else we go till feof. */ size_t left = file_size; bool use_left = !!res; TPM2B_MAX_BUFFER data; bool done = false; while (!done) { size_t bytes_read = fread(data.buffer, 1, BUFFER_SIZE(typeof(data), buffer), input); if (ferror(input)) { LOG_ERR("Error reading from input file"); return tool_rc_general_error; } data.size = bytes_read; /* if data was read, update the sequence */ rc = tpm2_sequence_update(ectx, sequence_handle, &data); if (rc != tool_rc_success) { return rc; } if (use_left) { left -= bytes_read; if (left <= TPM2_MAX_DIGEST_BUFFER) { done = true; continue; } } else if (feof(input)) { done = true; } } /* end file read/hash update loop */ if (use_left) { data.size = left; bool res = files_read_bytes(input, data.buffer, left); if (!res) { LOG_ERR("Error reading from input file."); return tool_rc_general_error; } } else { data.size = 0; } return tpm2_event_sequence_complete(ectx, ctx.pcr, sequence_handle, ctx.auth.session, &data, result); } static tool_rc do_pcrevent_and_output(ESYS_CONTEXT *ectx) { TPML_DIGEST_VALUES *digests = NULL; tool_rc rc = tpm_pcrevent_file(ectx, &digests); if (rc != tool_rc_success) { return rc; } assert(digests); UINT32 i; for (i = 0; i < digests->count; i++) { TPMT_HA *d = &digests->digests[i]; tpm2_tool_output("%s: ", tpm2_alg_util_algtostr(d->hashAlg, tpm2_alg_util_flags_hash)); const BYTE *bytes; size_t size; switch (d->hashAlg) { case TPM2_ALG_SHA1: bytes = d->digest.sha1; size = sizeof(d->digest.sha1); break; case TPM2_ALG_SHA256: bytes = d->digest.sha256; size = sizeof(d->digest.sha256); break; case TPM2_ALG_SHA384: bytes = d->digest.sha384; size = sizeof(d->digest.sha384); break; case TPM2_ALG_SHA512: bytes = d->digest.sha512; size = sizeof(d->digest.sha512); break; case TPM2_ALG_SM3_256: bytes = d->digest.sm3_256; size = sizeof(d->digest.sm3_256); break; default: { LOG_WARN("Unknown digest to convert!"); // print something so the format doesn't change // on this case. static const BYTE byte = 0; bytes = &byte; size = sizeof(byte); } } size_t j; for (j = 0; j < size; j++) { tpm2_tool_output("%02x", bytes[j]); } tpm2_tool_output("\n"); } free(digests); return tool_rc_success; } static bool on_arg(int argc, char **argv) { if (argc > 2) { LOG_ERR("Expected FILE and PCR index at most, got %d", argc); return false; } FILE *f = NULL; const char *pcr = NULL; unsigned i; /* argc can never be negative so cast is safe */ for (i = 0; i < (unsigned) argc; i++) { FILE *x = fopen(argv[i], "rb"); /* file already found but got another file */ if (f && x) { LOG_ERR("Only expected one file input"); fclose(x); goto error; /* looking for file and got a file so assign */ } else if (x && !f) { f = ctx.input = x; /* looking for pcr and not a file */ } else if (!pcr) { pcr = argv[i]; bool result = tpm2_util_handle_from_optarg(pcr, &ctx.pcr, TPM2_HANDLE_FLAGS_PCR); if (!result) { LOG_ERR("Could not convert \"%s\", to a pcr index.", pcr); return false; } /* got pcr and not a file (another pcr) */ } else { LOG_ERR("Already got PCR index."); goto error; } } return true; error: if (f) { fclose(f); } return false; } static bool on_option(char key, char *value) { switch (key) { case 'P': ctx.auth.auth_str = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "auth", required_argument, NULL, 'P' }, }; *opts = tpm2_options_new("P:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); ctx.input = ctx.input ? ctx.input : stdin; tool_rc rc = tpm2_auth_util_from_optarg(ectx, ctx.auth.auth_str, &ctx.auth.session, false); if (rc != tool_rc_success) { LOG_ERR("Invalid key handle authorization"); return rc; } return do_pcrevent_and_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.auth.session); } static void tpm2_tool_onexit(void) { if (ctx.input && ctx.input != stdin) { fclose(ctx.input); } } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("pcrevent", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_pcrextend.c000066400000000000000000000042721412464516500176570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_pcr_extend_ctx tpm_pcr_extend_ctx; struct tpm_pcr_extend_ctx { size_t digest_spec_len; tpm2_pcr_digest_spec *digest_spec; }; static tpm_pcr_extend_ctx ctx; static tool_rc pcr_extend_one(ESYS_CONTEXT *ectx, TPMI_DH_PCR pcr_index, TPML_DIGEST_VALUES *digests) {; TSS2_RC rval = Esys_PCR_Extend(ectx, pcr_index, ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE, digests); if (rval != TSS2_RC_SUCCESS) { LOG_ERR("Could not extend pcr index: 0x%X", pcr_index); LOG_PERR(Esys_PCR_Extend, rval); return tool_rc_from_tpm(rval); } return tool_rc_success; } static tool_rc pcr_extend(ESYS_CONTEXT *ectx) { size_t i; for (i = 0; i < ctx.digest_spec_len; i++) { tpm2_pcr_digest_spec *dspec = &ctx.digest_spec[i]; tool_rc rc = pcr_extend_one(ectx, dspec->pcr_index, &dspec->digests); if (rc != tool_rc_success) { return rc; } } return tool_rc_success; } static bool on_arg(int argc, char **argv) { if (argc < 1) { LOG_ERR("Expected at least one PCR Digest specification," "ie: :=, got: 0"); return false; } /* this can never be negative */ ctx.digest_spec_len = (size_t) argc; ctx.digest_spec = calloc(ctx.digest_spec_len, sizeof(*ctx.digest_spec)); if (!ctx.digest_spec) { LOG_ERR("oom"); return false; } return pcr_parse_digest_list(argv, ctx.digest_spec_len, ctx.digest_spec); } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); return pcr_extend(ectx); } static void tpm2_tool_onexit(void) { free(ctx.digest_spec); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("pcrextend", tpm2_tool_onstart, tpm2_tool_onrun, NULL, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_pcrread.c000066400000000000000000000102631412464516500173000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "log.h" #include "pcr.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_tool.h" typedef struct listpcr_context listpcr_context; struct listpcr_context { char *output_file_path; FILE *output_file; tpm2_convert_pcrs_output_fmt format; tpm2_algorithm algs; tpm2_pcrs pcrs; TPML_PCR_SELECTION pcr_selections; TPMI_ALG_HASH selected_algorithm; }; static listpcr_context ctx = { .format = pcrs_output_format_values }; static tool_rc show_pcr_list_selected_values(ESYS_CONTEXT *esys_context, TPMS_CAPABILITY_DATA *capdata, bool check) { if (check && !pcr_check_pcr_selection(capdata, &ctx.pcr_selections)) { return tool_rc_general_error; } tool_rc rc = pcr_read_pcr_values(esys_context, &ctx.pcr_selections, &ctx.pcrs); if (rc != tool_rc_success) { return rc; } bool success = pcr_print_values(&ctx.pcr_selections, &ctx.pcrs); if (success && ctx.output_file) { if (ctx.format == pcrs_output_format_values) { success = pcr_fwrite_values(&ctx.pcr_selections, &ctx.pcrs, ctx.output_file); } else if (ctx.format == pcrs_output_format_serialized) { success = pcr_fwrite_serialized(&ctx.pcr_selections, &ctx.pcrs, ctx.output_file); } } return success ? tool_rc_success : tool_rc_general_error; } static tool_rc show_pcr_alg_or_all_values(ESYS_CONTEXT *esys_context, TPMS_CAPABILITY_DATA *capdata) { bool res = pcr_init_pcr_selection(capdata, &ctx.pcr_selections, ctx.selected_algorithm); if (!res) { return tool_rc_general_error; } return show_pcr_list_selected_values(esys_context, capdata, false); } static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.output_file_path = value; break; case 'F': ctx.format = tpm2_convert_pcrs_output_fmt_from_optarg(value); if (ctx.format == pcrs_output_format_err) { return false; } break; /* no default */ } return true; } static bool on_arg(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Expected PCR list or algorithm selection"); return false; } ctx.selected_algorithm = tpm2_alg_util_from_optarg(argv[0], tpm2_alg_util_flags_hash); if (ctx.selected_algorithm == TPM2_ALG_ERROR) { bool res = pcr_parse_selections(argv[0], &ctx.pcr_selections); if (!res) { LOG_ERR("Neither algorithm nor pcr list, got: \"%s\"", argv[0]); return false; } } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "output", required_argument, NULL, 'o' }, { "pcrs_format", required_argument, NULL, 'F' }, }; *opts = tpm2_options_new("o:F:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *esys_context, tpm2_option_flags flags) { UNUSED(flags); if (ctx.output_file_path) { ctx.output_file = fopen(ctx.output_file_path, "wb+"); if (!ctx.output_file) { LOG_ERR("Could not open output file \"%s\" error: \"%s\"", ctx.output_file_path, strerror(errno)); return tool_rc_general_error; } } TPMS_CAPABILITY_DATA capdata; tool_rc rc = pcr_get_banks(esys_context, &capdata, &ctx.algs); if (rc != tool_rc_success) { return rc; } if (ctx.pcr_selections.count > 0) { return show_pcr_list_selected_values(esys_context, &capdata, true); } return show_pcr_alg_or_all_values(esys_context, &capdata); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *esys_context) { UNUSED(esys_context); if (ctx.output_file) { fclose(ctx.output_file); } return tool_rc_success; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("pcrread", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_pcrreset.c000066400000000000000000000032231412464516500175050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "pcr.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" typedef struct tpm_pcr_reset_ctx tpm_pcr_reset_ctx; struct tpm_pcr_reset_ctx { bool pcr_list[TPM2_MAX_PCRS]; }; static tpm_pcr_reset_ctx ctx; static tool_rc pcr_reset_one(ESYS_CONTEXT *ectx, TPMI_DH_PCR pcr_index) { tool_rc rc = tpm2_pcr_reset(ectx, pcr_index); if (rc != tool_rc_success) { LOG_ERR("Could not reset PCR index: %d", pcr_index); } return rc; } static tool_rc pcr_reset(ESYS_CONTEXT *ectx) { size_t i; for (i = 0; i < TPM2_MAX_PCRS; i++) { if (!ctx.pcr_list[i]) continue; tool_rc rc = pcr_reset_one(ectx, i); if (rc != tool_rc_success) { return rc; } } return tool_rc_success; } static bool on_arg(int argc, char** argv) { int i; uint32_t pcr; memset(ctx.pcr_list, 0, TPM2_MAX_PCRS); if (argc < 1) { LOG_ERR("Expected at least one PCR index" "ie: , got: 0"); return false; } for (i = 0; i < argc; i++) { if (!pcr_get_id(argv[i], &pcr)) return false; ctx.pcr_list[pcr] = 1; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); return pcr_reset(ectx); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("pcrreset", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_policyauthorize.c000066400000000000000000000063611412464516500211160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2_tool.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policyauthorize_ctx tpm2_policyauthorize_ctx; struct tpm2_policyauthorize_ctx { //File path for the session context data const char *session_path; //File path for the policy digest that will be authorized const char *policy_digest_path; //File path for the policy qualifier data const char *qualifier_data_path; //File path for the verifying public key name const char *verifying_pubkey_name_path; //File path for the verification ticket const char *ticket_path; //File path for storing the policy digest output const char *out_policy_dgst_path; tpm2_session *session; TPM2B_DIGEST *policy_digest; }; static tpm2_policyauthorize_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'L': ctx.out_policy_dgst_path = value; break; case 'S': ctx.session_path = value; break; case 'i': ctx.policy_digest_path = value; break; case 'q': ctx.qualifier_data_path = value; break; case 'n': ctx.verifying_pubkey_name_path = value; break; case 't': ctx.ticket_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "input", required_argument, NULL, 'i' }, { "qualification", required_argument, NULL, 'q' }, { "name", required_argument, NULL, 'n' }, { "ticket", required_argument, NULL, 't' }, }; *opts = tpm2_options_new("L:S:i:q:n:t:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } bool is_check_input_options_ok(void) { if (!ctx.session_path) { LOG_ERR("Must specify a session file with -S."); return false; } if (!ctx.verifying_pubkey_name_path) { LOG_ERR("Must specify name of the public key used for verification -n."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (!is_check_input_options_ok()) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policyauthorize(ectx, ctx.session, ctx.policy_digest_path, ctx.qualifier_data_path, ctx.verifying_pubkey_name_path, ctx.ticket_path); if (rc != tool_rc_success) { LOG_ERR("Could not build tpm authorized policy"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); free(ctx.policy_digest); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyauthorize", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyauthorizenv.c000066400000000000000000000105651412464516500214630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #include "tpm2_policy.h" typedef struct tpm_policyauthorizenv_ctx tpm_policyauthorizenv_ctx; struct tpm_policyauthorizenv_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; const char *out_policy_dgst_path; const char *session_path; tpm2_session *session; char *cp_hash_path; }; static tpm_policyauthorizenv_ctx ctx; static bool on_arg(int argc, char **argv) { /* If the user doesn't specify an authorization hierarchy use the index * passed to -x/--index for the authorization index. */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[0]; } return on_arg_nv_index(argc, argv, &ctx.nv_index); } static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'L': ctx.out_policy_dgst_path = value; break; case 'S': ctx.session_path = value; break; case 0: ctx.cp_hash_path = value; break; default: return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:L:S:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } if (ctx.cp_hash_path && ctx.out_policy_dgst_path) { LOG_WARN("Cannot output policyhash when calculating cphash."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } ESYS_TR policy_session_handle = tpm2_session_get_handle(ctx.session); if (!ctx.cp_hash_path) { rc = tpm2_policy_authorize_nv(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, policy_session_handle, NULL); if (rc != tool_rc_success) { return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_policy_authorize_nv(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, policy_session_handle, &cp_hash); if (rc != tool_rc_success) { goto cphash_error_out; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } else { goto cphash_out; } cphash_error_out: LOG_ERR("Failed cphash calculation operation"); cphash_out: return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tool_rc_success; tool_rc tmp_rc = tool_rc_success; if (!ctx.cp_hash_path) { tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } tmp_rc = tpm2_session_close(&ctx.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyauthorizenv", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyauthvalue.c000066400000000000000000000040531412464516500210760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policyauthvalue_ctx tpm2_policyauthvalue_ctx; struct tpm2_policyauthvalue_ctx { //File path for the session context data const char *session_path; //File path for storing the policy digest output const char *policy_digest_path; tpm2_session *session; }; static tpm2_policyauthvalue_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.session_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:L:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policyauthvalue(ectx, ctx.session); if (rc != tool_rc_success) { LOG_ERR("Could not build policyauthvalue TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyauthvalue", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policycommandcode.c000066400000000000000000000047051412464516500213550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2_cc_util.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policycommandcode_ctx tpm2_policycommandcode_ctx; struct tpm2_policycommandcode_ctx { const char *session_path; TPM2_CC command_code; const char *out_policy_dgst_path; tpm2_session *session; }; static tpm2_policycommandcode_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'S': ctx.session_path = value; break; case 'L': ctx.out_policy_dgst_path = value; break; } return true; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify only the TPM2 command code."); return false; } if (!argc) { LOG_ERR("TPM2 command code must be specified."); return false; } bool result = tpm2_cc_util_from_str(argv[0], &ctx.command_code); if (!result) { return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "session", required_argument, NULL, 'S' }, { "policy", required_argument, NULL, 'L' }, }; *opts = tpm2_options_new("S:L:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policycommandcode(ectx, ctx.session, ctx.command_code); if (rc != tool_rc_success) { LOG_ERR("Could not build TPM policy_command_code"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policycommandcode", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policycountertimer.c000066400000000000000000000157461412464516500216330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "log.h" #include "files.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #include "tpm2_policy.h" #define OFFSET_TPMS_TIME_INFO_TIME offsetof(TPMS_TIME_INFO, time) #define OFFSET_TPMS_TIME_INFO_CLOCK offsetof(TPMS_TIME_INFO, clockInfo.clock) #define OFFSET_TPMS_TIME_INFO_RESETS offsetof(TPMS_TIME_INFO, clockInfo.resetCount) #define OFFSET_TPMS_TIME_INFO_RESTARTS offsetof(TPMS_TIME_INFO, clockInfo.restartCount) #define OFFSET_TPMS_TIME_INFO_SAFE offsetof(TPMS_TIME_INFO, clockInfo.safe); typedef struct tpm_policycountertimer_ctx tpm_policycountertimer_ctx; struct tpm_policycountertimer_ctx { //Inputs const char *session_path; tpm2_session *session; TPM2B_OPERAND operand_b; uint16_t offset; bool operation_set; TPM2_EO operation; //Output const char *policy_digest_path; }; static tpm_policycountertimer_ctx ctx = { .operation = TPM2_EO_EQ, .offset = 0, }; static bool convert_keyvalue_to_operand_buffer(const char *value, uint16_t offset, uint8_t size) { ctx.offset = offset; /* * Convert input string data to a *big endian* uint64_t or uint32_t */ union data { uint32_t u32; uint64_t u64; uint8_t b; } data; bool result = false; switch(size) { case sizeof(uint32_t): result = tpm2_util_string_to_uint32(value, &data.u32); break; case sizeof(uint64_t): result = tpm2_util_string_to_uint64(value, &data.u64); break; default: LOG_ERR("Unknown size, got: %u", size); return false; } if (!result) { LOG_ERR("Invalid value specified for the key"); return false; } /* * sizes should be u32 or u64 and thus never overflow a TPM2B_OPPERAND * but we will check anyways in case something changes elsewhere. */ if (size > sizeof(ctx.operand_b.buffer)) { LOG_ERR("Size is too large for TPM2B_OPERAND. Got %u, max size is: %zu", size, sizeof(ctx.operand_b.buffer)); return false; } ctx.operand_b.size = size; size_t i = 0; for (i = 0; i < size; i++) { ctx.operand_b.buffer[i] = *(&data.b + size - i - 1); } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify one argument as value/ parameter=value."); return false; } if (!strcmp("safe", argv[0])) { ctx.offset = OFFSET_TPMS_TIME_INFO_SAFE; ctx.operand_b.size = 1; ctx.operand_b.buffer[0] = TPM2_YES; return true; } const char *value; const char *key; char *a = argv[0]; char *split = strchr(a, '='); if (!split) { value = argv[0]; key = "time"; } else { split[0] = '\0'; value = split + 1; key = a; } if (!value[0]) { LOG_ERR("Must specify a corresponding value"); return false; } // look up key and process value if (!strcmp("time", key)) { return convert_keyvalue_to_operand_buffer(value, OFFSET_TPMS_TIME_INFO_TIME, sizeof(uint64_t)); } if (!strcmp("clock", key)) { return convert_keyvalue_to_operand_buffer(value, OFFSET_TPMS_TIME_INFO_CLOCK, sizeof(uint64_t)); } if (!strcmp("resets", key)) { return convert_keyvalue_to_operand_buffer(value, OFFSET_TPMS_TIME_INFO_RESETS, sizeof(uint32_t)); } if (!strcmp("restarts", key)) { return convert_keyvalue_to_operand_buffer(value, OFFSET_TPMS_TIME_INFO_RESTARTS, sizeof(uint32_t)); } LOG_ERR("Unknown argument. Specify time/ clock/ resets/ restarts/ safe"); return false; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.session_path = value; break; case TPM2_EO_EQ: case TPM2_EO_NEQ: case TPM2_EO_SIGNED_GT: case TPM2_EO_UNSIGNED_GT: case TPM2_EO_SIGNED_LT: case TPM2_EO_UNSIGNED_LT: case TPM2_EO_SIGNED_GE: case TPM2_EO_UNSIGNED_GE: case TPM2_EO_SIGNED_LE: case TPM2_EO_UNSIGNED_LE: case TPM2_EO_BITSET: case TPM2_EO_BITCLEAR: if (ctx.operation_set) { LOG_ERR("Only one operator can be specified"); return false; } ctx.operation_set = true; ctx.operation = key; break; default: return false; } return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "eq", no_argument, NULL, TPM2_EO_EQ }, { "neq", no_argument, NULL, TPM2_EO_NEQ }, { "sgt", no_argument, NULL, TPM2_EO_SIGNED_GT }, { "ugt", no_argument, NULL, TPM2_EO_UNSIGNED_GT }, { "slt", no_argument, NULL, TPM2_EO_SIGNED_LT }, { "ult", no_argument, NULL, TPM2_EO_UNSIGNED_LT }, { "sge", no_argument, NULL, TPM2_EO_SIGNED_GE }, { "uge", no_argument, NULL, TPM2_EO_UNSIGNED_GE }, { "sle", no_argument, NULL, TPM2_EO_SIGNED_LE }, { "ule", no_argument, NULL, TPM2_EO_UNSIGNED_LE }, { "bs", no_argument, NULL, TPM2_EO_BITSET }, { "bc", no_argument, NULL, TPM2_EO_BITCLEAR }, }; *opts = tpm2_options_new("L:S:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.operand_b.size) { LOG_WARN("Data to compare is of size 0"); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool result = is_input_option_args_valid(); if (!result) { return tool_rc_general_error; } //Input tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } ESYS_TR policy_session = tpm2_session_get_handle(ctx.session); //ESAPI call rc = tpm2_policy_countertimer(ectx, policy_session, &ctx.operand_b, ctx.offset, ctx.operation); if (rc != tool_rc_success) { return rc; } //Output return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policycountertimer", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policycphash.c000066400000000000000000000050551412464516500203510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policycphash_ctx tpm2_policycphash_ctx; struct tpm2_policycphash_ctx { //Input TPM2B_DIGEST cphash; //Input/Output const char *session_file_path; tpm2_session *session; //Output const char *policy_digest_file_path; }; static tpm2_policycphash_ctx ctx; static bool process_input_cphash(char *value) { bool result = files_load_digest(value, &ctx.cphash); if (!result) { LOG_ERR("Failed loading creation hash."); } return result; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_file_path = value; break; case 'S': ctx.session_file_path = value; break; case 0: result = process_input_cphash(value); break; } return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "cphash-input", required_argument, NULL, 0 }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("L:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_file_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.cphash.size) { LOG_ERR("CpHash file is of size zero."); } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_file_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policycphash(ectx, ctx.session, &ctx.cphash); if (rc != tool_rc_success) { LOG_ERR("Could not build policycphash TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_file_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policycphash", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyduplicationselect.c000066400000000000000000000054741412464516500226230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policyduplicationselect_ctx tpm2_policyduplicationselect_ctx; struct tpm2_policyduplicationselect_ctx { const char *session_path; const char *obj_name_path; const char *new_parent_name_path; const char *out_policy_dgst_path; TPMI_YES_NO is_include_obj; TPM2B_DIGEST *policy_digest; tpm2_session *session; }; static tpm2_policyduplicationselect_ctx ctx; static bool on_option(char key, char *value) { ctx.is_include_obj = 0; switch (key) { case 'S': ctx.session_path = value; break; case 'n': ctx.obj_name_path = value; break; case 'N': ctx.new_parent_name_path = value; break; case 'L': ctx.out_policy_dgst_path = value; break; case 0: ctx.is_include_obj = 1; break; } return true; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.new_parent_name_path) { LOG_ERR("Must specify -N object new parent file."); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "session", required_argument, NULL, 'S' }, { "object-name", required_argument, NULL, 'n' }, { "parent-name", required_argument, NULL, 'N' }, { "policy", required_argument, NULL, 'L' }, { "include-object", no_argument, NULL, 0 }, }; *opts = tpm2_options_new("S:n:N:L:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policyduplicationselect(ectx, ctx.session, ctx.obj_name_path, ctx.new_parent_name_path, ctx.is_include_obj); if (rc != tool_rc_success) { LOG_ERR("Could not build TPM policy_duplication_select"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); free(ctx.policy_digest); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyduplicationselect", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policylocality.c000066400000000000000000000060441412464516500207220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policylocality_ctx tpm2_policylocality_ctx; struct tpm2_policylocality_ctx { const char *session_path; TPMA_LOCALITY locality; const char *out_policy_dgst_path; TPM2B_DIGEST *policy_digest; tpm2_session *session; }; static tpm2_policylocality_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'S': ctx.session_path = value; break; case 'L': ctx.out_policy_dgst_path = value; break; } return true; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify only the TPM2 locality."); return false; } if (!argc) { LOG_ERR("TPM2 locality must be specified."); return false; } if (strcmp(argv[0], "zero")) { ctx.locality = TPMA_LOCALITY_TPM2_LOC_ZERO; } else if (strcmp(argv[0], "one")) { ctx.locality = TPMA_LOCALITY_TPM2_LOC_ONE; } else if (strcmp(argv[0], "two")) { ctx.locality = TPMA_LOCALITY_TPM2_LOC_TWO; } else if (strcmp(argv[0], "three")) { ctx.locality = TPMA_LOCALITY_TPM2_LOC_THREE; } else if (strcmp(argv[0], "four")) { ctx.locality = TPMA_LOCALITY_TPM2_LOC_FOUR; } else { bool result = tpm2_util_string_to_uint8(argv[0], &ctx.locality); if (!result) { LOG_ERR("Could not convert locality to number, got: \"%s\"", argv[0]); return false; } } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "session", required_argument, NULL, 'S' }, { "policy", required_argument, NULL, 'L' }, }; *opts = tpm2_options_new("S:L:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policylocality(ectx, ctx.session, ctx.locality); if (rc != tool_rc_success) { LOG_ERR("Could not build TPM policy_locality"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); free(ctx.policy_digest); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policylocality", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policynamehash.c000066400000000000000000000052441412464516500206670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policynamehash_ctx tpm2_policynamehash_ctx; struct tpm2_policynamehash_ctx { //Input TPM2B_DIGEST name_hash; //Input/Output const char *session_file_path; tpm2_session *session; //Output const char *policy_digest_file_path; }; static tpm2_policynamehash_ctx ctx; static bool process_input_name_hash(char *value) { ctx.name_hash.size = sizeof(ctx.name_hash.buffer); bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, value, &ctx.name_hash.size, ctx.name_hash.buffer); if (!result) { LOG_ERR("Failed loading name hash from file"); return false; } return true; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_file_path = value; break; case 'S': ctx.session_file_path = value; break; case 'n': result = process_input_name_hash(value); break; } return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "name", required_argument, NULL, 'n' }, }; *opts = tpm2_options_new("L:S:n:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_file_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.name_hash.size) { LOG_WARN("Name-hash file is of size zero"); } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_file_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policynamehash(ectx, ctx.session, &ctx.name_hash); if (rc != tool_rc_success) { LOG_ERR("Could not build policynamehash TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_file_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policynamehash", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policynv.c000066400000000000000000000175401412464516500175300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_nv_util.h" #include "tpm2_options.h" #include "tpm2_policy.h" typedef struct tpm_policynv_ctx tpm_policynv_ctx; struct tpm_policynv_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } auth_hierarchy; TPM2_HANDLE nv_index; const char *policy_digest_path; const char *session_path; tpm2_session *session; TPM2B_OPERAND operand_b; UINT16 offset; TPM2_EO operation; char *cp_hash_path; }; static tpm_policynv_ctx ctx = { .operand_b = { .size = BUFFER_SIZE(TPM2B_OPERAND, buffer) } }; static bool on_arg(int argc, char **argv) { switch (argc) { case 2: break; default: goto on_arg_error; } uint8_t argv_index_ctr = argc; do { argv_index_ctr--; if (!strcmp(argv[argv_index_ctr], "eq")) { ctx.operation = TPM2_EO_EQ; } else if (!strcmp(argv[argv_index_ctr], "neq")) { ctx.operation = TPM2_EO_NEQ; } else if (!strcmp(argv[argv_index_ctr], "sgt")) { ctx.operation = TPM2_EO_SIGNED_GT; } else if (!strcmp(argv[argv_index_ctr], "ugt")) { ctx.operation = TPM2_EO_UNSIGNED_GT; } else if (!strcmp(argv[argv_index_ctr], "slt")) { ctx.operation = TPM2_EO_SIGNED_LT; } else if (!strcmp(argv[argv_index_ctr], "ult")) { ctx.operation = TPM2_EO_UNSIGNED_LT; } else if (!strcmp(argv[argv_index_ctr], "sge")) { ctx.operation = TPM2_EO_SIGNED_GE; } else if (!strcmp(argv[argv_index_ctr], "uge")) { ctx.operation = TPM2_EO_UNSIGNED_GE; } else if (!strcmp(argv[argv_index_ctr], "sle")) { ctx.operation = TPM2_EO_SIGNED_LE; } else if (!strcmp(argv[argv_index_ctr], "ule")) { ctx.operation = TPM2_EO_UNSIGNED_LE; } else if (!strcmp(argv[argv_index_ctr], "bs")) { ctx.operation = TPM2_EO_BITSET; } else if (!strcmp(argv[argv_index_ctr], "bc")) { ctx.operation = TPM2_EO_BITCLEAR; } else { // Process it as NV index instead /* * Use the index as an authorization hierarchy If the user doesn't specify */ if (!ctx.auth_hierarchy.ctx_path) { ctx.auth_hierarchy.ctx_path = argv[argv_index_ctr]; } return on_arg_nv_index( 1, argv, &ctx.nv_index); //Only 1 arg for NV index } } while(argv_index_ctr > 0); // Loop to iterate through the two arguments /* * Invalid argument specified */ on_arg_error: LOG_ERR("Specify 2 arguments - NV-Index and Comparison-Operartion"); return false; } static bool on_option(char key, char *value) { bool result = false; char *input_file; switch (key) { case 'C': ctx.auth_hierarchy.ctx_path = value; break; case 'P': ctx.auth_hierarchy.auth_str = value; break; case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.session_path = value; break; case 'i': input_file = strcmp("-", value) ? value : NULL; if (input_file) { result = files_get_file_size_path(value, (long unsigned *) &ctx.operand_b.size); } if (input_file && !result) { return false; } result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, input_file, &ctx.operand_b.size, ctx.operand_b.buffer); if (!result) { return false; } break; case 0: if (!tpm2_util_string_to_uint16(value, &ctx.offset)) { LOG_ERR("Could not convert starting offset, got: \"%s\"", value); return false; } break; case 1: ctx.cp_hash_path = value; break; default: return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "input", required_argument, NULL, 'i' }, { "offset", required_argument, NULL, 0 }, { "cphash", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("C:P:L:S:i:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } if (ctx.cp_hash_path && ctx.policy_digest_path) { LOG_WARN("Cannot output policyhash when calculating cphash."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } if (!ctx.operand_b.size) { LOG_WARN("Data to compare is of size 0"); } /* * Ensure that NV index is large enough to compare the size of input data. */ TPM2B_NV_PUBLIC *nv_public = NULL; tool_rc rc = tpm2_util_nv_read_public(ectx, ctx.nv_index, &nv_public); if (rc != tool_rc_success) { LOG_ERR("Failed to access NVRAM public area at index 0x%X", ctx.nv_index); free(nv_public); return rc; } if (ctx.operand_b.size > nv_public->nvPublic.dataSize - ctx.offset) { LOG_ERR("The operand size is larger than NV data" " starting at the offset"); free(nv_public); return tool_rc_general_error; } free(nv_public); rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path, ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false, TPM2_HANDLE_FLAGS_NV | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { LOG_ERR("Invalid handle authorization"); return rc; } rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } ESYS_TR policy_session_handle = tpm2_session_get_handle(ctx.session); if (!ctx.cp_hash_path) { rc = tpm2_policy_nv(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, policy_session_handle, &ctx.operand_b, ctx.offset, ctx.operation, NULL); if (rc != tool_rc_success) { return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_policy_nv(ectx, &ctx.auth_hierarchy.object, ctx.nv_index, policy_session_handle, &ctx.operand_b, ctx.offset, ctx.operation, &cp_hash); if (rc != tool_rc_success) { goto cphash_error_out; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } else { goto cphash_out; } cphash_error_out: LOG_ERR("Failed cphash calculation operation"); cphash_out: return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); tool_rc rc = tool_rc_success; tool_rc tmp_rc = tool_rc_success; if (!ctx.cp_hash_path) { tmp_rc = tpm2_session_close(&ctx.auth_hierarchy.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } tmp_rc = tpm2_session_close(&ctx.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policynv", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policynvwritten.c000066400000000000000000000057661412464516500211540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2_cc_util.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policynvwritten_ctx tpm2_policynvwritten_ctx; struct tpm2_policynvwritten_ctx { const char *session_path; const char *policy_digest_path; tpm2_session *session; TPMI_YES_NO written_set; }; static tpm2_policynvwritten_ctx ctx = { .written_set = TPM2_NO, }; static bool on_option(char key, char *value) { switch (key) { case 'S': ctx.session_path = value; break; case 'L': ctx.policy_digest_path = value; break; } return true; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify single NV written SET/CLEAR operation as s|c|0|1."); return false; } if (!argc) { LOG_ERR("Disable NV written SET/CLEAR operation must be specified."); return false; } if (!strcmp(argv[0], "s")) { ctx.written_set = TPM2_YES; return true; } if (!strcmp(argv[0], "c")) { ctx.written_set = TPM2_NO; return true; } uint32_t value; bool result = tpm2_util_string_to_uint32(argv[0], &value); if (!result) { LOG_ERR("Please specify 0|1|s|c. Could not convert string, got: \"%s\"", argv[0]); return false; } if (value != TPM2_NO && value != TPM2_YES) { LOG_ERR("Please use 0|1|s|c as the argument to specify operation"); return false; } ctx.written_set = value; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "session", required_argument, NULL, 'S' }, { "policy", required_argument, NULL, 'L' }, }; *opts = tpm2_options_new("S:L:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policynvwritten(ectx, ctx.session, ctx.written_set); if (rc != tool_rc_success) { LOG_ERR("Could not build policy_nv_written!"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policynvwritten", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyor.c000066400000000000000000000070231412464516500175200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policyor_ctx tpm2_policyor_ctx; struct tpm2_policyor_ctx { //File path for the session context data const char *session_path; //List of policy digests that will be compounded TPML_DIGEST *policy_list; //File path for storing the policy digest output const char *out_policy_dgst_path; TPM2B_DIGEST *policy_digest; tpm2_session *session; }; static tpm2_policyor_ctx ctx; static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.out_policy_dgst_path = value; break; case 'S': ctx.session_path = value; break; case 'l': ctx.policy_list = calloc(1, sizeof(TPML_DIGEST)); result = tpm2_policy_parse_policy_list(value, ctx.policy_list); if (!result) { return false; } break; } return result; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("specify single argument for policy list."); return false; } ctx.policy_list = calloc(1, sizeof(TPML_DIGEST)); bool result = tpm2_policy_parse_policy_list(argv[0], ctx.policy_list); if (!result) { return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, //Option retained for backwards compatibility - See issue#1894 { "policy-list", required_argument, NULL, 'l' }, }; *opts = tpm2_options_new("L:S:l:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } //Minimum two policies needed to be specified for compounding if (ctx.policy_list->count < 1) { LOG_ERR("Must specify at least 2 policy digests for compounding."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } /* Policy digest hash alg should match that of the session */ if (ctx.policy_list->digests[0].size != tpm2_alg_util_get_hash_size( tpm2_session_get_authhash(ctx.session))) { LOG_ERR("Policy digest hash alg should match that of the session."); return tool_rc_general_error; } rc = tpm2_policy_build_policyor(ectx, ctx.session, ctx.policy_list); if (rc != tool_rc_success) { LOG_ERR("Could not build policyor TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); free(ctx.policy_list); free(ctx.policy_digest); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyor", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policypassword.c000066400000000000000000000040521412464516500207410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policypassword_ctx tpm2_policypassword_ctx; struct tpm2_policypassword_ctx { //File path for the session context data const char *session_path; //File path for storing the policy digest output const char *out_policy_dgst_path; tpm2_session *session; }; static tpm2_policypassword_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'L': ctx.out_policy_dgst_path = value; break; case 'S': ctx.session_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:L:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policypassword(ectx, ctx.session); if (rc != tool_rc_success) { LOG_ERR("Could not build policypassword TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.out_policy_dgst_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policypassword", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policypcr.c000066400000000000000000000063511412464516500176670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "pcr.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policypcr_ctx tpm2_policypcr_ctx; struct tpm2_policypcr_ctx { const char *session_path; const char *raw_pcrs_file; TPML_PCR_SELECTION pcr_selection; const char *policy_out_path; TPM2B_DIGEST *raw_pcr_digest; tpm2_session *session; }; static tpm2_policypcr_ctx ctx; static bool on_arg(int argc, char **argv) { if ((ctx.raw_pcrs_file && argv[0]) || argc > 1) { LOG_ERR("Specify either pcr-digest or pcr data, not both"); return false; } ctx.raw_pcr_digest = malloc(sizeof(TPM2B_DIGEST)); if (!ctx.raw_pcr_digest) { LOG_ERR("oom"); return tool_rc_general_error; } int q; ctx.raw_pcr_digest->size = BUFFER_SIZE(TPM2B_DIGEST, buffer); if ((q = tpm2_util_hex_to_byte_structure(argv[0], &ctx.raw_pcr_digest->size, ctx.raw_pcr_digest->buffer)) != 0) { free(ctx.raw_pcr_digest); LOG_ERR("FAILED: %d", q); return false; } return true; } static bool on_option(char key, char *value) { switch (key) { case 'L': ctx.policy_out_path = value; break; case 'f': ctx.raw_pcrs_file = value; break; case 'l': { bool result = pcr_parse_selections(value, &ctx.pcr_selection); if (!result) { LOG_ERR("Could not parse PCR selections"); return false; } } break; case 'S': ctx.session_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "pcr", required_argument, NULL, 'f' }, { "pcr-list", required_argument, NULL, 'l' }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("L:f:l:S:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool option_fail = false; if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); option_fail = true; } if (!ctx.pcr_selection.count) { LOG_ERR("Must specify -l pcr selection list."); option_fail = true; } if (option_fail) { return tool_rc_general_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_pcr(ectx, ctx.session, ctx.raw_pcrs_file, &ctx.pcr_selection, ctx.raw_pcr_digest); if (rc != tool_rc_success) { LOG_ERR("Could not build pcr policy"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_out_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); free(ctx.raw_pcr_digest); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policypcr", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyrestart.c000066400000000000000000000023311412464516500205610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "log.h" #include "tpm2_tool.h" #include "tpm2_options.h" typedef struct tpm2_policyreset_ctx tpm2_policyreset_ctx; struct tpm2_policyreset_ctx { char *path; tpm2_session *session; }; static tpm2_policyreset_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'S': ctx.path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_session_restore(ectx, ctx.path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } return tpm2_session_restart(ectx, ctx.session); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyrestart", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policysecret.c000066400000000000000000000157751412464516500204020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policysecret_ctx tpm2_policysecret_ctx; struct tpm2_policysecret_ctx { struct { const char *ctx_path; //auth_entity.ctx_path const char *auth_str; //auth_str tpm2_loaded_object object; //context_object && pwd_session } auth_entity; //File path for storing the policy digest output const char *policy_digest_path; //File path for the session context data const char *extended_session_path; tpm2_session *extended_session; INT32 expiration; char *policy_ticket_path; char *policy_timeout_path; const char *qualifier_data_arg; bool is_nonce_tpm; struct { UINT8 c :1; } flags; char *cp_hash_path; }; static tpm2_policysecret_ctx ctx; static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.extended_session_path = value; break; case 'c': ctx.auth_entity.ctx_path = value; ctx.flags.c = 1; break; case 0: ctx.policy_ticket_path = value; break; case 1: ctx.policy_timeout_path = value; break; case 't': result = tpm2_util_string_to_int32(value, &ctx.expiration); if (!result) { LOG_ERR("Failed reading expiration duration from value, got:\"%s\"", value); return false; } break; case 'x': ctx.is_nonce_tpm = true; break; case 'q': ctx.qualifier_data_arg = value; break; case 2: ctx.cp_hash_path = value; break; } return result; } static bool on_arg(int argc, char **argv) { if (argc > 1) { LOG_ERR("Specify a single auth value"); return false; } if (!argc) { //empty auth return true; } ctx.auth_entity.auth_str = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "object-context", required_argument, NULL, 'c' }, { "expiration", required_argument, NULL, 't' }, { "nonce-tpm", no_argument, NULL, 'x' }, { "ticket", required_argument, NULL, 0 }, { "timeout", required_argument, NULL, 1 }, { "qualification", required_argument, NULL, 'q' }, { "cphash", required_argument, NULL, 2 }, }; *opts = tpm2_options_new("L:S:c:t:q:x", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.extended_session_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.flags.c) { LOG_ERR("Must specify -c handle-id/ context file path."); return false; } if (ctx.cp_hash_path && ctx.policy_digest_path) { LOG_WARN("Cannot output policyhash when calculating cphash."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool result = is_input_option_args_valid(); if (!result) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.extended_session_path, false, &ctx.extended_session); if (rc != tool_rc_success) { return rc; } /* * The auth string of the referenced object is strictly for a password session */ rc = tpm2_util_object_load_auth(ectx, ctx.auth_entity.ctx_path, ctx.auth_entity.auth_str, &ctx.auth_entity.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } if (!ctx.cp_hash_path) { /* * Build a policysecret using the pwd session. If the event of * a failure: * 1. always close the pwd session. * 2. log the policy secret failure and return tool_rc_general_error. * 3. if the error was closing the policy secret session, return that rc. */ TPMT_TK_AUTH *policy_ticket = NULL; TPM2B_TIMEOUT *timeout = NULL; rc = tpm2_policy_build_policysecret(ectx, ctx.extended_session, &ctx.auth_entity.object, ctx.expiration, &policy_ticket, &timeout, ctx.is_nonce_tpm, ctx.qualifier_data_arg, NULL); tool_rc rc2 = tpm2_session_close(&ctx.auth_entity.object.session); if (rc != tool_rc_success) { goto tpm2_tool_onrun_out; } if (rc2 != tool_rc_success) { rc = rc2; goto tpm2_tool_onrun_out; } rc = tpm2_policy_tool_finish(ectx, ctx.extended_session, ctx.policy_digest_path); if (rc != tool_rc_success) { goto tpm2_tool_onrun_out; } if (ctx.policy_timeout_path) { if(!timeout->size) { LOG_WARN("Policy assertion did not produce timeout"); } else { result = files_save_bytes_to_file(ctx.policy_timeout_path, timeout->buffer, timeout->size); } } if (!result) { LOG_ERR("Failed to save timeout to file."); rc = tool_rc_general_error; goto tpm2_tool_onrun_out; } if (ctx.policy_ticket_path) { if (!policy_ticket->digest.size) { LOG_WARN("Policy assertion did not produce auth ticket."); } else { result = files_save_authorization_ticket(policy_ticket, ctx.policy_ticket_path); } } if (!result) { LOG_ERR("Failed to save auth ticket"); rc = tool_rc_general_error; } tpm2_tool_onrun_out: free(policy_ticket); free(timeout); if (rc != tool_rc_success) { LOG_ERR("Could not build policysecret"); } return rc; } TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_policy_build_policysecret(ectx, ctx.extended_session, &ctx.auth_entity.object, ctx.expiration, NULL, NULL, ctx.is_nonce_tpm, ctx.qualifier_data_arg, &cp_hash); if (rc != tool_rc_success) { LOG_ERR("Failed cphash calculation operation"); return rc; } result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { LOG_ERR("Failed saving command parameter hash for policysecret"); rc = tool_rc_general_error; } return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.extended_session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policysecret", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policysigned.c000066400000000000000000000157351412464516500203620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policysigned_ctx tpm2_policysigned_ctx; struct tpm2_policysigned_ctx { const char *session_path; tpm2_session *session; const char *policy_digest_path; TPMT_SIGNATURE signature; TPMI_ALG_SIG_SCHEME format; TPMI_ALG_HASH halg; char *sig_file_path; const char *context_arg; tpm2_loaded_object key_context_object; bool is_nonce_tpm; INT32 expiration; char *policy_ticket_path; char *policy_timeout_path; const char *raw_data_path; const char *cphash_path; const char *policy_qualifier_data; union { struct { UINT8 halg :1; UINT8 sig :1; UINT8 fmt :1; }; UINT8 all; } flags; }; static tpm2_policysigned_ctx ctx = { .signature = { .sigAlg = TPM2_ALG_RSASSA, .signature.rsassa.hash = TPM2_ALG_SHA256, }, .halg = TPM2_ALG_SHA256 }; static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.session_path = value; break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Unable to convert algorithm, got: \"%s\"", value); return false; } ctx.flags.halg = 1; break; case 'f': ctx.format = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.format == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } ctx.flags.fmt = 1; break; case 's': ctx.sig_file_path = value; ctx.flags.sig = 1; break; case 'c': ctx.context_arg = value; break; case 'q': ctx.policy_qualifier_data = value; break; case 0: ctx.policy_ticket_path = value; break; case 1: ctx.policy_timeout_path = value; break; case 2: ctx.raw_data_path = value; break; case 3: ctx.cphash_path = value; break; case 'x': ctx.is_nonce_tpm = true; break; case 't': result = tpm2_util_string_to_int32(value, &ctx.expiration); if (!result) { LOG_ERR("Failed reading expiration duration from value, got:\"%s\"", value); return false; } } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "signature", required_argument, NULL, 's' }, { "format", required_argument, NULL, 'f' }, { "key-context", required_argument, NULL, 'c' }, { "expiration", required_argument, NULL, 't' }, { "qualification", required_argument, NULL, 'q' }, { "nonce-tpm", no_argument, NULL, 'x' }, { "ticket", required_argument, NULL, 0 }, { "timeout", required_argument, NULL, 1 }, { "raw-data", required_argument, NULL, 2 }, { "cphash-input", required_argument, NULL, 3 }, }; *opts = tpm2_options_new("L:S:g:s:f:c:t:q:x", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.context_arg) { LOG_ERR("Must specify verifying key context -c."); return false; } if (ctx.raw_data_path) { if (ctx.is_nonce_tpm && !ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } if (ctx.flags.sig) { tpm2_convert_sig_fmt fmt = ctx.flags.fmt ? signature_format_plain : signature_format_tss; bool res = tpm2_convert_sig_load(ctx.sig_file_path, fmt, ctx.format, ctx.halg, &ctx.signature); if (!res) { return tool_rc_general_error; } } /* * For signature verification only object load is needed, not auth. */ tool_rc tmp_rc = tpm2_util_object_load(ectx, ctx.context_arg, &ctx.key_context_object, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (tmp_rc != tool_rc_success) { return tmp_rc; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } TPM2B_TIMEOUT *timeout = NULL; TPMT_TK_AUTH *policy_ticket = NULL; rc = tpm2_policy_build_policysigned(ectx, ctx.session, &ctx.key_context_object, &ctx.signature, ctx.expiration, &timeout, &policy_ticket, ctx.policy_qualifier_data, ctx.is_nonce_tpm, ctx.raw_data_path, ctx.cphash_path); if (rc != tool_rc_success) { LOG_ERR("Could not build policysigned TPM"); goto tpm2_tool_onrun_out; } if (ctx.raw_data_path) { goto tpm2_tool_onrun_out; } rc = tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); if (rc != tool_rc_success) { goto tpm2_tool_onrun_out; } if (ctx.policy_timeout_path) { if(!timeout->size) { LOG_WARN("Policy assertion did not produce timeout"); } else { retval = files_save_bytes_to_file(ctx.policy_timeout_path, timeout->buffer, timeout->size); } } if (!retval) { LOG_ERR("Failed to save timeout to file."); rc = tool_rc_general_error; goto tpm2_tool_onrun_out; } if (ctx.policy_ticket_path) { if (!policy_ticket->digest.size) { LOG_WARN("Policy assertion did not produce auth ticket."); } else { retval = files_save_authorization_ticket(policy_ticket, ctx.policy_ticket_path); } } if (!retval) { LOG_ERR("Failed to save auth ticket"); rc = tool_rc_general_error; } tpm2_tool_onrun_out: free(timeout); free(policy_ticket); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policysigned", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policytemplate.c000066400000000000000000000053321412464516500207140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policytemplate_ctx tpm2_policytemplate_ctx; struct tpm2_policytemplate_ctx { //Input TPM2B_DIGEST template_hash; //Input/Output const char *session_file_path; tpm2_session *session; //Output const char *policy_digest_file_path; }; static tpm2_policytemplate_ctx ctx; static bool process_input_template_hash(char *value) { ctx.template_hash.size = sizeof(ctx.template_hash.buffer); bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, value, &ctx.template_hash.size, ctx.template_hash.buffer); if (!result) { LOG_ERR("Failed loading name hash from file"); return false; } return true; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'L': ctx.policy_digest_file_path = value; break; case 'S': ctx.session_file_path = value; break; case 0: result = process_input_template_hash(value); break; } return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "template-hash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("L:S:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_file_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.template_hash.size) { LOG_WARN("Template-hash file is of size zero"); } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_file_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policytemplate(ectx, ctx.session, &ctx.template_hash); if (rc != tool_rc_success) { LOG_ERR("Could not build policytemplate TPM"); return rc; } return tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_file_path); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policytemplate", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_policyticket.c000066400000000000000000000063131412464516500203640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_policyticket_ctx tpm2_policyticket_ctx; struct tpm2_policyticket_ctx { const char *session_path; tpm2_session *session; const char *policy_digest_path; char *policy_timeout_path; const char *policy_qualifier_data; char *policy_ticket_path; const char *auth_name_file; }; static tpm2_policyticket_ctx ctx; static bool on_option(char key, char *value) { switch (key) { case 'L': ctx.policy_digest_path = value; break; case 'S': ctx.session_path = value; break; case 'n': ctx.auth_name_file = value; break; case 'q': ctx.policy_qualifier_data = value; break; case 0: ctx.policy_ticket_path = value; break; case 1: ctx.policy_timeout_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy", required_argument, NULL, 'L' }, { "session", required_argument, NULL, 'S' }, { "name", required_argument, NULL, 'n' }, { "qualification", required_argument, NULL, 'q' }, { "ticket", required_argument, NULL, 0 }, { "timeout", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("L:S:n:q:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify -S session file."); return false; } if (!ctx.auth_name_file) { LOG_ERR("Must specify -n authname file."); return false; } if (!ctx.policy_ticket_path) { LOG_ERR("Must specify --ticket policy ticket file."); return false; } if (!ctx.policy_timeout_path) { LOG_ERR("Must specify --timeout policy timeout file."); return false; } return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = tpm2_session_restore(ectx, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { return rc; } rc = tpm2_policy_build_policyticket(ectx, ctx.session, ctx.policy_timeout_path, ctx.policy_qualifier_data, ctx.policy_ticket_path, ctx.auth_name_file); if (rc != tool_rc_success) { LOG_ERR("Could not build policyticket TPM"); return rc; } rc = tpm2_policy_tool_finish(ectx, ctx.session, ctx.policy_digest_path); if (rc != tool_rc_success) { return rc; } return tool_rc_success; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("policyticket", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_quote.c000066400000000000000000000225571412464516500170260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_openssl.h" #include "tpm2_systemdeps.h" #include "tpm2_tool.h" typedef struct tpm_quote_ctx tpm_quote_ctx; struct tpm_quote_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } key; char *signature_path; char *message_path; char *pcr_path; FILE *pcr_output; tpm2_convert_sig_fmt sig_format; TPMI_ALG_HASH sig_hash_algorithm; tpm2_algorithm algs; TPM2B_DATA qualification_data; TPML_PCR_SELECTION pcr_selections; TPMS_CAPABILITY_DATA cap_data; tpm2_pcrs pcrs; tpm2_convert_pcrs_output_fmt pcrs_format; char *cp_hash_path; }; static tpm_quote_ctx ctx = { .sig_hash_algorithm = TPM2_ALG_NULL, .qualification_data = TPM2B_EMPTY_INIT, .pcrs_format = pcrs_output_format_serialized, }; static bool write_output_files(TPM2B_ATTEST *quoted, TPMT_SIGNATURE *signature) { bool res = true; if (ctx.signature_path) { res &= tpm2_convert_sig_save(signature, ctx.sig_format, ctx.signature_path); } if (ctx.message_path) { res &= files_save_bytes_to_file(ctx.message_path, (UINT8*) quoted->attestationData, quoted->size); } if (ctx.pcr_output) { if (ctx.pcrs_format == pcrs_output_format_serialized) { res &= pcr_fwrite_serialized(&ctx.pcr_selections, &ctx.pcrs, ctx.pcr_output); } else if (ctx.pcrs_format == pcrs_output_format_values) { res &= pcr_fwrite_values(&ctx.pcr_selections, &ctx.pcrs, ctx.pcr_output); } } return res; } static tool_rc quote(ESYS_CONTEXT *ectx, TPML_PCR_SELECTION *pcr_selection) { TPM2B_ATTEST *quoted = NULL; TPMT_SIGNATURE *signature = NULL; TPMT_SIG_SCHEME in_scheme = { .scheme = TPM2_ALG_NULL }; tool_rc rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.key.object.tr_handle, &ctx.sig_hash_algorithm, TPM2_ALG_NULL, &in_scheme); if (rc != tool_rc_success) { return rc; } if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_quote(ectx, &ctx.key.object, &in_scheme, &ctx.qualification_data, pcr_selection, "ed, &signature, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } rc = tpm2_quote(ectx, &ctx.key.object, &in_scheme, &ctx.qualification_data, pcr_selection, "ed, &signature, NULL); if (rc != tool_rc_success) { return rc; } tpm2_tool_output("quoted: "); tpm2_util_print_tpm2b(quoted); tpm2_tool_output("\nsignature:\n"); tpm2_tool_output(" alg: %s\n", tpm2_alg_util_algtostr(signature->sigAlg, tpm2_alg_util_flags_sig)); UINT16 size; BYTE *sig = tpm2_convert_sig(&size, signature); if (!sig) { return tool_rc_general_error; } tpm2_tool_output(" sig: "); tpm2_util_hexdump(sig, size); tpm2_tool_output("\n"); free(sig); if (ctx.pcr_output) { // Filter out invalid/unavailable PCR selections if (!pcr_check_pcr_selection(&ctx.cap_data, &ctx.pcr_selections)) { LOG_ERR("Failed to filter unavailable PCR values for quote!"); return tool_rc_general_error; } // Gather PCR values from the TPM (the quote doesn't have them!) rc = pcr_read_pcr_values(ectx, &ctx.pcr_selections, &ctx.pcrs); if (rc != tool_rc_success) { LOG_ERR("Failed to retrieve PCR values related to quote!"); return rc; } // Grab the digest from the quote TPMS_ATTEST attest; rc = files_tpm2b_attest_to_tpms_attest(quoted, &attest); if (rc != tool_rc_success) { return rc; } // Print out PCR values as output if (!pcr_print_pcr_struct(&ctx.pcr_selections, &ctx.pcrs)) { LOG_ERR("Failed to print PCR values related to quote!"); return tool_rc_general_error; } // Calculate the digest from our selected PCR values (to ensure correctness) TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer); if (!tpm2_openssl_hash_pcr_banks(ctx.sig_hash_algorithm, &ctx.pcr_selections, &ctx.pcrs, &pcr_digest)) { LOG_ERR("Failed to hash PCR values related to quote!"); return tool_rc_general_error; } tpm2_tool_output("calcDigest: "); tpm2_util_hexdump(pcr_digest.buffer, pcr_digest.size); tpm2_tool_output("\n"); // Make sure digest from quote matches calculated PCR digest if (!tpm2_util_verify_digests(&attest.attested.quote.pcrDigest, &pcr_digest)) { LOG_ERR("Error validating calculated PCR composite with quote"); return tool_rc_general_error; } } // Write everything out bool res = write_output_files(quoted, signature); free(quoted); free(signature); return res ? tool_rc_success : tool_rc_general_error; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.key.ctx_path = value; break; case 'p': ctx.key.auth_str = value; break; case 'l': if (!pcr_parse_selections(value, &ctx.pcr_selections)) { LOG_ERR("Could not parse pcr selections, got: \"%s\"", value); return false; } break; case 'q': ctx.qualification_data.size = sizeof(ctx.qualification_data.buffer); return tpm2_util_bin_from_hex_or_file(value, &ctx.qualification_data.size, ctx.qualification_data.buffer); break; case 's': ctx.signature_path = value; break; case 'm': ctx.message_path = value; break; case 'o': ctx.pcr_path = value; break; case 'F': ctx.pcrs_format = tpm2_convert_pcrs_output_fmt_from_optarg(value); if (ctx.pcrs_format == pcrs_output_format_err) { return false; } break; case 'f': ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } break; case 'g': ctx.sig_hash_algorithm = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.sig_hash_algorithm == TPM2_ALG_ERROR) { LOG_ERR( "Could not convert signature hash algorithm selection, got: \"%s\"", value); return false; } break; case 0: ctx.cp_hash_path = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "key-context", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "pcr-list", required_argument, NULL, 'l' }, { "qualification", required_argument, NULL, 'q' }, { "signature", required_argument, NULL, 's' }, { "message", required_argument, NULL, 'm' }, { "pcr", required_argument, NULL, 'o' }, { "pcrs_format", required_argument, NULL, 'F' }, { "format", required_argument, NULL, 'f' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "cphash", required_argument, NULL, 0 } }; *opts = tpm2_options_new("c:p:l:q:s:m:o:F:f:g:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* TODO this whole file needs to be re-done, especially the option validation */ if (!ctx.pcr_selections.count) { LOG_ERR("Expected -l to be specified."); return tool_rc_option_error; } if (ctx.cp_hash_path && (ctx.signature_path || ctx.message_path)) { LOG_ERR("Cannot produce output when calculating cpHash"); return tool_rc_option_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.key.ctx_path, ctx.key.auth_str, &ctx.key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } if (ctx.pcr_path) { ctx.pcr_output = fopen(ctx.pcr_path, "wb+"); if (!ctx.pcr_output) { LOG_ERR("Could not open PCR output file \"%s\" error: \"%s\"", ctx.pcr_path, strerror(errno)); return tool_rc_general_error; } } rc = pcr_get_banks(ectx, &ctx.cap_data, &ctx.algs); if (rc != tool_rc_success) { return rc; } return quote(ectx, &ctx.pcr_selections); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); if (ctx.pcr_output) { fclose(ctx.pcr_output); } return tpm2_session_close(&ctx.key.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("quote", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_readclock.c000066400000000000000000000010401412464516500176000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_util.h" static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); TPMS_TIME_INFO *current_time = NULL; tool_rc rc = tpm2_readclock(ectx, ¤t_time); if (rc == tool_rc_success) { tpm2_util_print_time(current_time); Esys_Free(current_time); } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("readclock", NULL, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_readpublic.c000066400000000000000000000105351412464516500177740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_convert.h" #include "tpm2_tool.h" typedef struct tpm_readpub_ctx tpm_readpub_ctx; struct tpm_readpub_ctx { struct { UINT8 f :1; } flags; char *output_path; char *out_name_file; char *out_qname_file; tpm2_convert_pubkey_fmt format; tpm2_loaded_object context_object; const char *context_arg; const char *out_tr_file; }; static tpm_readpub_ctx ctx = { .format = pubkey_format_tss, }; static tool_rc read_public_and_save(ESYS_CONTEXT *ectx) { TPM2B_PUBLIC *public; TPM2B_NAME *name; TPM2B_NAME *qualified_name; tool_rc rc = tool_rc_general_error; tool_rc tmp_rc = tpm2_readpublic(ectx, ctx.context_object.tr_handle, &public, &name, &qualified_name); if (tmp_rc != tool_rc_success) { return tmp_rc; } tpm2_tool_output("name: "); UINT16 i; for (i = 0; i < name->size; i++) { tpm2_tool_output("%02x", name->name[i]); } tpm2_tool_output("\n"); bool ret = true; if (ctx.out_name_file) { ret = files_save_bytes_to_file(ctx.out_name_file, name->name, name->size); if (!ret) { LOG_ERR("Can not save object name file."); goto out; } } tpm2_tool_output("qualified name: "); for (i = 0; i < qualified_name->size; i++) { tpm2_tool_output("%02x", qualified_name->name[i]); } tpm2_tool_output("\n"); tpm2_util_public_to_yaml(public, NULL); ret = ctx.output_path ? tpm2_convert_pubkey_save(public, ctx.format, ctx.output_path) : true; if (!ret) { goto out; } if (ctx.out_qname_file) { ret = files_save_bytes_to_file(ctx.out_qname_file, qualified_name->name, qualified_name->size); if (!ret) { goto out; } } if (ctx.out_tr_file) { rc = files_save_ESYS_TR(ectx, ctx.context_object.tr_handle, ctx.out_tr_file); } else { rc = tool_rc_success; } out: free(public); free(name); free(qualified_name); return rc; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.context_arg = value; break; case 'o': ctx.output_path = value; break; case 'f': ctx.format = tpm2_convert_pubkey_fmt_from_optarg(value); if (ctx.format == pubkey_format_err) { return false; } ctx.flags.f = 1; break; case 'n': ctx.out_name_file = value; break; case 't': ctx.out_tr_file = value; break; case 'q': ctx.out_qname_file = value; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "output", required_argument, NULL, 'o' }, { "object-context", required_argument, NULL, 'c' }, { "format", required_argument, NULL, 'f' }, { "name", required_argument, NULL, 'n' }, { "serialized-handle", required_argument, NULL, 't' }, { "qualified-name", required_argument, NULL, 'q' } }; *opts = tpm2_options_new("o:c:f:n:t:q:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc init(ESYS_CONTEXT *context) { tool_rc rc = tpm2_util_object_load(context, ctx.context_arg, &ctx.context_object, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } bool is_persistent = ctx.context_object.handle && ((ctx.context_object.handle >> TPM2_HR_SHIFT) == TPM2_HT_PERSISTENT); if (ctx.out_tr_file && !is_persistent) { LOG_ERR("Can only output a serialized handle for persistent object " "handles"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = init(context); if (rc != tool_rc_success) { return rc; } return read_public_and_save(context); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("readpublic", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_rsadecrypt.c000066400000000000000000000123551412464516500200440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_rsadecrypt_ctx tpm_rsadecrypt_ctx; struct tpm_rsadecrypt_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } key; TPM2B_DATA label; TPM2B_PUBLIC_KEY_RSA cipher_text; char *input_path; char *output_file_path; TPMT_RSA_DECRYPT scheme; const char *scheme_str; char *cp_hash_path; }; static tpm_rsadecrypt_ctx ctx = { .scheme = { .scheme = TPM2_ALG_RSAES } }; static tool_rc rsa_decrypt_and_save(ESYS_CONTEXT *ectx) { TPM2B_PUBLIC_KEY_RSA *message = NULL; if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_rsa_decrypt(ectx, &ctx.key.object, &ctx.cipher_text, &ctx.scheme, &ctx.label, &message, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } tool_rc rc = tpm2_rsa_decrypt(ectx, &ctx.key.object, &ctx.cipher_text, &ctx.scheme, &ctx.label, &message, NULL); if (rc != tool_rc_success) { return rc; } bool ret = false; FILE *f = ctx.output_file_path ? fopen(ctx.output_file_path, "wb+") : stdout; if (!f) { goto out; } ret = files_write_bytes(f, message->buffer, message->size); if (f != stdout) { fclose(f); } out: free(message); return ret ? tool_rc_success : tool_rc_general_error; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.key.ctx_path = value; break; case 'p': ctx.key.auth_str = value; break; case 'o': { ctx.output_file_path = value; break; } case 's': ctx.scheme_str = value; break; case 0: ctx.cp_hash_path = value; break; case 'l': return tpm2_util_get_label(value, &ctx.label); } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Only supports one input file, got: %d", argc); return false; } ctx.input_path = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "output", required_argument, NULL, 'o' }, { "key-context", required_argument, NULL, 'c' }, { "scheme", required_argument, NULL, 's' }, { "label", required_argument, NULL, 'l' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("p:o:c:s:l:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc init(ESYS_CONTEXT *ectx) { if (!ctx.key.ctx_path) { LOG_ERR("Expected argument -c."); return tool_rc_option_error; } if (ctx.output_file_path && ctx.cp_hash_path) { LOG_ERR("Cannout decrypt when calculating cphash"); return tool_rc_option_error; } /* * Load the decryption key */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.key.ctx_path, ctx.key.auth_str, &ctx.key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { return rc; } TPM2B_PUBLIC *key_public_info = 0; rc = tpm2_readpublic(ectx, ctx.key.object.tr_handle, &key_public_info, NULL, NULL); if (rc != tool_rc_success) { goto out; } if (key_public_info->publicArea.type != TPM2_ALG_RSA) { LOG_ERR("Unsupported key type for RSA decryption."); rc = tool_rc_general_error; goto out; } /* * Get scheme information */ if (ctx.scheme_str) { rc = tpm2_alg_util_handle_rsa_ext_alg(ctx.scheme_str, key_public_info); ctx.scheme.scheme = key_public_info->publicArea.parameters.rsaDetail.scheme.scheme; ctx.scheme.details.anySig.hashAlg = key_public_info->publicArea.parameters.rsaDetail.scheme.details.anySig.hashAlg; if (rc != tool_rc_success) { goto out; } } /* * Get enc data blob */ ctx.cipher_text.size = BUFFER_SIZE(TPM2B_PUBLIC_KEY_RSA, buffer); bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_path, &ctx.cipher_text.size, ctx.cipher_text.buffer); if (!result) { rc = tool_rc_general_error; } out: Esys_Free(key_public_info); return rc; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = init(ectx); if (rc != tool_rc_success) { return rc; } return rsa_decrypt_and_save(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.key.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("rsadecrypt", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_rsaencrypt.c000066400000000000000000000101061412464516500200460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_rsaencrypt_ctx tpm_rsaencrypt_ctx; struct tpm_rsaencrypt_ctx { const char *context_arg; tpm2_loaded_object key_context; TPM2B_PUBLIC_KEY_RSA message; char *output_path; char *input_path; TPMT_RSA_DECRYPT scheme; const char *scheme_str; TPM2B_DATA label; }; static tpm_rsaencrypt_ctx ctx = { .context_arg = NULL, .scheme = { .scheme = TPM2_ALG_RSAES } }; static tool_rc rsa_encrypt_and_save(ESYS_CONTEXT *context) { bool ret = false; TPM2B_PUBLIC_KEY_RSA *out_data = NULL; tool_rc rc = tpm2_rsa_encrypt(context, &ctx.key_context, &ctx.message, &ctx.scheme, &ctx.label, &out_data); if (rc != tool_rc_success) { return rc; } FILE *f = ctx.output_path ? fopen(ctx.output_path, "wb+") : stdout; if (!f) { goto out; } ret = files_write_bytes(f, out_data->buffer, out_data->size); if (f != stdout) { fclose(f); } out: free(out_data); return ret ? tool_rc_success : tool_rc_general_error; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.context_arg = value; break; case 'o': ctx.output_path = value; break; case 's': ctx.scheme_str = value; break; case 'l': return tpm2_util_get_label(value, &ctx.label); } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Only supports one input file, got: %d", argc); return false; } ctx.input_path = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { {"output", required_argument, NULL, 'o'}, {"key-context", required_argument, NULL, 'c'}, {"scheme", required_argument, NULL, 's'}, {"label", required_argument, NULL, 'l'}, }; *opts = tpm2_options_new("o:c:s:l:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc init(ESYS_CONTEXT *context) { if (!ctx.context_arg) { LOG_ERR("Expected option c"); return tool_rc_option_error; } ctx.message.size = BUFFER_SIZE(TPM2B_PUBLIC_KEY_RSA, buffer); bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_path, &ctx.message.size, ctx.message.buffer); if (!result) { return tool_rc_general_error; } /* * Load the decryption key */ tool_rc rc = tpm2_util_object_load(context, ctx.context_arg, &ctx.key_context, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { return rc; } TPM2B_PUBLIC *key_public_info = 0; rc = tpm2_readpublic(context, ctx.key_context.tr_handle, &key_public_info, NULL, NULL); if (rc != tool_rc_success) { goto out; } if (key_public_info->publicArea.type != TPM2_ALG_RSA) { LOG_ERR("Unsupported key type for RSA decryption."); rc = tool_rc_general_error; goto out; } /* * Get scheme information */ if (ctx.scheme_str) { rc = tpm2_alg_util_handle_rsa_ext_alg(ctx.scheme_str, key_public_info); ctx.scheme.scheme = key_public_info->publicArea.parameters.rsaDetail.scheme.scheme; ctx.scheme.details.anySig.hashAlg = key_public_info->publicArea.parameters.rsaDetail.scheme.details.anySig.hashAlg; } out: Esys_Free(key_public_info); return rc; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = init(context); if (rc != tool_rc_success) { return rc; } return rsa_encrypt_and_save(context); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("rsaencrypt", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_selftest.c000066400000000000000000000020571412464516500175130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" typedef struct tpm_selftest_ctx tpm_selftest_ctx; struct tpm_selftest_ctx { TPMI_YES_NO fulltest; }; static tpm_selftest_ctx ctx; static bool on_option(char key, char *value) { UNUSED(value); switch (key) { case 'f': ctx.fulltest = TPM2_YES; break; default: LOG_ERR("Invalid option."); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "fulltest", no_argument, NULL, 'f' } }; ctx.fulltest = TPM2_NO; *opts = tpm2_options_new("f", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); return tpm2_selftest(ectx, ctx.fulltest); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("selftest", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_send.c000066400000000000000000000142721412464516500166150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include "files.h" #include "log.h" #include "tpm2_header.h" #include "tpm2_tool.h" typedef struct tpm2_send_ctx tpm2_send_ctx; struct tpm2_send_ctx { FILE *input; FILE *output; tpm2_command_header *command; }; typedef void (*sighandler_t)(int); static tpm2_send_ctx ctx; static void sig_handler(int signum) { UNUSED(signum); exit (tool_rc_success); } static int read_command_from_file(FILE *f, tpm2_command_header **c, UINT32 *size) { UINT8 buffer[TPM2_COMMAND_HEADER_SIZE]; size_t ret = fread(buffer, TPM2_COMMAND_HEADER_SIZE, 1, f); if (ret != 1 && ferror(f) && errno != EINTR) { LOG_ERR("Failed to read command header: %s", strerror (errno)); return -1; } if (feof(f) || ferror(f)) { return 0; } tpm2_command_header *header = tpm2_command_header_from_bytes(buffer); UINT32 command_size = tpm2_command_header_get_size(header, true); UINT32 data_size = tpm2_command_header_get_size(header, false); if (command_size > TPM2_MAX_SIZE || command_size < data_size) { LOG_ERR("Command buffer %"PRIu32" bytes cannot be smaller then the " "encapsulated data %"PRIu32" bytes, and can not be bigger than" " the maximum buffer size", command_size, data_size); return -1; } tpm2_command_header *command = (tpm2_command_header *) malloc(command_size); if (!command) { LOG_ERR("oom"); return -1; } /* copy the header into the struct */ memcpy(command, buffer, sizeof(buffer)); LOG_INFO("command tag: 0x%04x", tpm2_command_header_get_tag(command)); LOG_INFO("command size: 0x%08x", command_size); LOG_INFO("command code: 0x%08x", tpm2_command_header_get_code(command)); ret = fread(command->data, data_size, 1, f); if (ret != 1 && ferror(f)) { LOG_ERR("Failed to read command body: %s", strerror (errno)); free(command); return -1; } *c = command; *size = command_size; return 1; } static bool write_response_to_file(FILE *f, UINT8 *rbuf) { tpm2_response_header *r = tpm2_response_header_from_bytes(rbuf); UINT32 size = tpm2_response_header_get_size(r, true); LOG_INFO("response tag: 0x%04x", tpm2_response_header_get_tag(r)); LOG_INFO("response size: 0x%08x", size); LOG_INFO("response code: 0x%08x", tpm2_response_header_get_code(r)); bool rc = files_write_bytes(f, r->bytes, size); fflush(f); return rc; } static FILE *open_file(const char *path, const char *mode) { FILE *f = fopen(path, mode); if (!f) { LOG_ERR("Could not open \"%s\", error: \"%s\"", path, strerror(errno)); } return f; } static void close_file(FILE *f) { if (f && (f != stdin || f != stdout)) { fclose(f); } } static bool on_option(char key, char *value) { switch (key) { case 'o': ctx.output = open_file(value, "wb"); if (!ctx.output) { return false; } break; /* no break */ } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Expected 1 tpm buffer input file, got: %d", argc); return false; } ctx.input = fopen(argv[0], "rb"); if (!ctx.input) { LOG_ERR("Error opening file \"%s\", error: %s", argv[0], strerror(errno)); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "output", required_argument, NULL, 'o' }, }; *opts = tpm2_options_new("o:", ARRAY_LEN(topts), topts, on_option, on_args, 0); ctx.input = stdin; ctx.output = stdout; return *opts != NULL; } /* * This program reads a TPM command buffer from stdin then dumps it out * to a tabd TCTI. It then reads the response from the TCTI and writes it * to stdout. Like the TCTI, we expect the input TPM command buffer to be * in network byte order (big-endian). We output the response in the same * form. */ static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); sighandler_t old_handler = signal(SIGINT, sig_handler); if(old_handler == SIG_ERR) { LOG_WARN("Could not set SIGINT handler: %s", strerror(errno)); } TSS2_TCTI_CONTEXT *tcti_context; TSS2_RC rval = Esys_GetTcti(context, &tcti_context); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_GetTctiContext, rval); return tool_rc_from_tpm(rval); } while (1) { UINT32 size; int result = read_command_from_file(ctx.input, &ctx.command, &size); if (result < 0) { LOG_ERR("failed to read TPM2 command buffer from file"); return tool_rc_general_error; } else if (result == 0) { return tool_rc_success; } rval = Tss2_Tcti_Transmit(tcti_context, size, ctx.command->bytes); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("tss2_tcti_transmit failed: 0x%x", rval); return tool_rc_from_tpm(rval); } size_t rsize = TPM2_MAX_SIZE; UINT8 rbuf[TPM2_MAX_SIZE]; rval = Tss2_Tcti_Receive(tcti_context, &rsize, rbuf, TSS2_TCTI_TIMEOUT_BLOCK); if (rval != TPM2_RC_SUCCESS) { LOG_ERR("tss2_tcti_receive failed: 0x%x", rval); return tool_rc_from_tpm(rval); } /* * The response buffer, rbuf, all fields are in big-endian, and we save * in big-endian. */ result = write_response_to_file(ctx.output, rbuf); if (!result) { LOG_ERR("Failed writing response to output file."); return tool_rc_general_error; } free(ctx.command); ctx.command = NULL; } /* shouldn't be possible */ return tool_rc_success; } static void tpm2_tool_onexit(void) { close_file(ctx.input); close_file(ctx.output); free(ctx.command); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("send", tpm2_tool_onstart, tpm2_tool_onrun, NULL, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_sessionconfig.c000066400000000000000000000135011412464516500205270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct tpm_sessionconfig_ctx tpm_sessionconfig_ctx; struct tpm_sessionconfig_ctx { tpm2_session *session; const char *session_path; TPMA_SESSION bmask; TPMA_SESSION flags; }; static tpm_sessionconfig_ctx ctx; #define PRINT_SESSION_ATTRIBUTE(ATTR, attr) \ do { \ if (attrs & ATTR) { \ if (is_attr_set) { \ tpm2_tool_output("|"); \ } else { \ is_attr_set = true; \ } \ tpm2_tool_output(attr); \ } \ } while(false) static tool_rc process_output(ESYS_CONTEXT *esys_context) { ESYS_TR sessionhandle = tpm2_session_get_handle(ctx.session); if (!sessionhandle) { LOG_ERR("Session handle cannot be null"); return tool_rc_general_error; } if (ctx.bmask) { return Esys_TRSess_SetAttributes(esys_context, sessionhandle, ctx.flags, ctx.bmask); } TPM2_HANDLE tpm_handle; TSS2_RC rv = Esys_TR_GetTpmHandle(esys_context, sessionhandle, &tpm_handle); if (rv != TSS2_RC_SUCCESS) { return tool_rc_general_error; } /* * Describe session attributes */ TPMA_SESSION attrs = 0; tool_rc rc = tpm2_sess_get_attributes(esys_context, sessionhandle, &attrs); if (rc != tool_rc_success) { return rc; } tpm2_tool_output("Session-Handle: 0x%.8"PRIx32"\n", tpm_handle); bool is_attr_set = false; tpm2_tool_output("Session-Attributes: "); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_CONTINUESESSION, "continuesession"); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_AUDITEXCLUSIVE, "auditexclusive"); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_AUDITRESET, "auditreset"); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_DECRYPT, "decrypt"); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_ENCRYPT, "encrypt"); PRINT_SESSION_ATTRIBUTE(TPMA_SESSION_AUDIT, "audit"); tpm2_tool_output("\n"); return tool_rc_success; } static tool_rc process_input(ESYS_CONTEXT *esys_context) { tool_rc rc = tpm2_session_restore(esys_context, ctx.session_path, false, &ctx.session); if (rc != tool_rc_success) { LOG_ERR("Could not restore session from the specified file"); return rc; } return tool_rc_success; } static bool on_option(char key, char *value) { UNUSED(value); switch (key) { case 0: ctx.bmask |= TPMA_SESSION_CONTINUESESSION; ctx.flags |= TPMA_SESSION_CONTINUESESSION; break; case 1: ctx.bmask |= TPMA_SESSION_CONTINUESESSION; break; case 2: ctx.bmask |= TPMA_SESSION_AUDITEXCLUSIVE; ctx.flags |= TPMA_SESSION_AUDITEXCLUSIVE; break; case 3: ctx.bmask |= TPMA_SESSION_AUDITEXCLUSIVE; break; case 4: ctx.bmask |= TPMA_SESSION_AUDITRESET; ctx.flags |= TPMA_SESSION_AUDITRESET; break; case 5: ctx.bmask |= TPMA_SESSION_AUDITRESET; break; case 6: ctx.bmask |= TPMA_SESSION_DECRYPT; ctx.flags |= TPMA_SESSION_DECRYPT; break; case 7: ctx.bmask |= TPMA_SESSION_DECRYPT; break; case 8: ctx.bmask |= TPMA_SESSION_ENCRYPT; ctx.flags |= TPMA_SESSION_ENCRYPT; break; case 9: ctx.bmask |= TPMA_SESSION_ENCRYPT; break; case 10: ctx.bmask |= TPMA_SESSION_AUDIT; ctx.flags |= TPMA_SESSION_AUDIT; break; case 11: ctx.bmask |= TPMA_SESSION_AUDIT; break; } return true; } static bool on_args(int argc, char **argv) { if (argc > 1) { LOG_ERR("Argument takes one file name for session data"); return false; } ctx.session_path = argv[0]; return true; } static bool is_input_option_args_valid(void) { if (!ctx.session_path) { LOG_ERR("Must specify session file as an argument."); return false; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "enable-continuesession", no_argument, NULL, 0 }, { "disable-continuesession", no_argument, NULL, 1 }, { "enable-auditexclusive", no_argument, NULL, 2 }, { "disable-auditexclusive", no_argument, NULL, 3 }, { "enable-auditreset", no_argument, NULL, 4 }, { "disable-auditreset", no_argument, NULL, 5 }, { "enable-decrypt", no_argument, NULL, 6 }, { "disable-decrypt", no_argument, NULL, 7 }, { "enable-encrypt", no_argument, NULL, 8 }, { "disable-encrypt", no_argument, NULL, 9 }, { "enable-audit", no_argument, NULL, 10 }, { "disable-audit", no_argument, NULL, 11 }, }; *opts = tpm2_options_new(NULL, ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *esys_context, tpm2_option_flags flags) { UNUSED(flags); bool retval = is_input_option_args_valid(); if (!retval) { return tool_rc_option_error; } tool_rc rc = process_input(esys_context); if(rc != tool_rc_success) { return rc; } return process_output(esys_context); /* * Disabling continuesession should flush the session after use. */ } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *esys_context) { UNUSED(esys_context); return tpm2_session_close(&ctx.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("sessionconfig", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_setclock.c000066400000000000000000000054211412464516500174670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_util.h" typedef struct tpm2_setclock_ctx tpm2_setclock_ctx; struct tpm2_setclock_ctx { bool time_set; UINT64 new_time; const char *auth_hierarchy; tpm2_loaded_object object; const char *auth_value; char *cp_hash_path; }; static tpm2_setclock_ctx ctx = { .auth_hierarchy = "o" /* default to owner hierarchy */ }; static bool on_arg(int argc, char **argv) { if (argc != 1) { LOG_ERR("Can only specify 1 time to set, got: %d", argc); return false; } bool result = tpm2_util_string_to_uint64(argv[0], &ctx.new_time); if (!result) { LOG_ERR("Could not convert argument to time, got: \"%s\"", argv[0]); return false; } ctx.time_set = true; return true; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.auth_hierarchy = value; break; case 'p': ctx.auth_value = value; break; case 0: ctx.cp_hash_path = value; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "hierarchy", required_argument, NULL, 'c' }, { "auth", required_argument, NULL, 'p' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("c:p:", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (!ctx.time_set) { LOG_ERR("Expected single argument of time to set"); return tool_rc_general_error; } tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy, ctx.auth_value, &ctx.object, false, TPM2_HANDLE_FLAGS_P|TPM2_HANDLE_FLAGS_O); if (rc != tool_rc_success) { return rc; } if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; LOG_WARN("Calculating cpHash. Exiting without setting clock."); rc = tpm2_setclock(ectx, &ctx.object, ctx.new_time, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } return tpm2_setclock(ectx, &ctx.object, ctx.new_time, NULL); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("setclock", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_setcommandauditstatus.c000066400000000000000000000070651412464516500223130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_cc_util.h" #include "tpm2_policy.h" #include "tpm2_tool.h" typedef struct tpm2_setcommandauditstatus_ctx tpm2_setcommandauditstatus_ctx; struct tpm2_setcommandauditstatus_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } hierarchy; TPML_CC command_code_list; TPMI_ALG_HASH hash_algorithm; bool clear_list; }; static tpm2_setcommandauditstatus_ctx ctx = { .hierarchy = { .ctx_path = "o", }, .hash_algorithm = TPM2_ALG_SHA256, .clear_list = false }; static bool on_option(char key, char *value) { switch (key) { case 'C': ctx.hierarchy.ctx_path = value; break; case 'P': ctx.hierarchy.auth_str = value; break; case 'c': ctx.clear_list = true; break; case 'g': ctx.hash_algorithm = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.hash_algorithm == TPM2_ALG_ERROR) { return false; } break; default: LOG_ERR("Unknown option"); return false; } return true; } static bool on_arg(int argc, char **argv) { if (argc > 1 || !argc) { LOG_ERR("Specify a TPM2 command to add/ remove from audit list."); return false; } if (ctx.command_code_list.count > TPM2_MAX_CAP_CC) { LOG_ERR("List of commands exceeds maximum supported command count"); return false; } bool result = tpm2_cc_util_from_str(argv[0], &ctx.command_code_list.commandCodes[ctx.command_code_list.count]); if (!result) { return false; } ctx.command_code_list.count+=1; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "hierarchy-auth", required_argument, NULL, 'P' }, { "clear-list", no_argument, NULL, 'c' }, { "hash-algorithm", required_argument, NULL, 'g' }, }; *opts = tpm2_options_new("C:P:g:c", ARRAY_LEN(topts), topts, on_option, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.hierarchy.ctx_path, ctx.hierarchy.auth_str , &ctx.hierarchy.object, false, TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P); if (rc != tool_rc_success) { return rc; } TPML_CC empty_list = { 0 }; /* * TPM does not allow to set commandaudit digest and commands to audit * simultaneously. So first set the command audit digest. */ rc = tpm2_setcommandcodeaudit(ectx, &ctx.hierarchy.object, ctx.hash_algorithm, &empty_list, &empty_list); if (rc != tool_rc_success) { LOG_ERR("Failed to set command audit digest."); return rc; } rc = ctx.clear_list ? tpm2_setcommandcodeaudit(ectx, &ctx.hierarchy.object, ctx.hash_algorithm, &empty_list, &ctx.command_code_list) : tpm2_setcommandcodeaudit(ectx, &ctx.hierarchy.object, ctx.hash_algorithm, &ctx.command_code_list, &empty_list); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("setcommandauditstatus", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_setprimarypolicy.c000066400000000000000000000114261412464516500213010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_nv_util.h" #include "tpm2_tool.h" typedef struct tpm_setprimarypolicy_ctx tpm_setprimarypolicy_ctx; struct tpm_setprimarypolicy_ctx { //Input struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } hierarchy; const char *policy_path; TPMI_ALG_HASH hash_algorithm; char *cp_hash_path; }; static tpm_setprimarypolicy_ctx ctx = { .hash_algorithm = TPM2_ALG_NULL, }; static bool set_digest_algorithm(char *value) { ctx.hash_algorithm = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.hash_algorithm == TPM2_ALG_ERROR) { LOG_ERR("Could not convert to number or lookup algorithm, got: " "\"%s\"", value); return false; } return true; } static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'C': ctx.hierarchy.ctx_path = value; break; case 'P': ctx.hierarchy.auth_str = value; break; case 'L': ctx.policy_path = value; break; case 'g': result = set_digest_algorithm(value); break; case 0: ctx.cp_hash_path = value; break; } return result; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "hierarchy", required_argument, NULL, 'C' }, { "auth", required_argument, NULL, 'P' }, { "policy", required_argument, NULL, 'L' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "cphash", required_argument, NULL, 0 }, }; *opts = tpm2_options_new("C:P:L:g:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static bool is_input_options_args_valid(void) { if (!ctx.hierarchy.ctx_path) { LOG_ERR("Must specify the hierarchy '-C'."); return false; } bool result = true; if (ctx.policy_path) { unsigned long file_size = 0; result = files_get_file_size_path(ctx.policy_path, &file_size); if (!result || file_size == 0) { result = false; } } if (ctx.cp_hash_path) { LOG_WARN("Calculating cpHash. Exiting without setting primary policy."); } return result; } static tool_rc process_setprimarypolicy_input(ESYS_CONTEXT *ectx, TPM2B_DIGEST **auth_policy) { /* * Load hierarchy handle and auth */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.hierarchy.ctx_path, ctx.hierarchy.auth_str, &ctx.hierarchy.object, false, TPM2_HANDLE_FLAGS_O|TPM2_HANDLE_FLAGS_P|TPM2_HANDLE_FLAGS_E| TPM2_HANDLE_FLAGS_L); if (rc != tool_rc_success) { return rc; } /* * Load policy digest if one is specified */ if (ctx.policy_path) { *auth_policy = malloc(UINT16_MAX + sizeof(uint16_t)); if (!*auth_policy) { LOG_ERR("oom"); return tool_rc_general_error; } (*auth_policy)->size = UINT16_MAX; bool result = files_load_bytes_from_path(ctx.policy_path, (*auth_policy)->buffer, &((*auth_policy)->size)); if (!result) { LOG_ERR("Failed loading policy digest from path"); return tool_rc_general_error; } } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { /* opts is unused, avoid compiler warning */ UNUSED(flags); bool result = is_input_options_args_valid(); if (!result) { return tool_rc_option_error; } //Input TPM2B_DIGEST *auth_policy = NULL; tool_rc rc = process_setprimarypolicy_input(ectx, &auth_policy); if (rc != tool_rc_success) { return rc; } //ESAPI call if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; rc = tpm2_setprimarypolicy(ectx, &ctx.hierarchy.object, auth_policy, ctx.hash_algorithm, &cp_hash); if (rc != tool_rc_success) { goto out; } result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } goto out; } rc = tpm2_setprimarypolicy(ectx, &ctx.hierarchy.object, auth_policy, ctx.hash_algorithm, NULL); out: free(auth_policy); return rc; } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.hierarchy.object.session); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("setprimarypolicy", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_shutdown.c000066400000000000000000000025111412464516500175300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "tpm2.h" #include "tpm2_tool.h" /* * Both the Microsoft and IBM TPM2 simulators require some specific setup * before they can be used by the SAPI. This setup is specific to the * simulators and is something that the low-level hardware / firmware does * for a discrete TPM. * NOTE: In the code that interacts with a TPM this can be a very ugly * abstraction leak. */ typedef struct tpm2_shutdown_ctx tpm2_shutdown_ctx; struct tpm2_shutdown_ctx { UINT8 clear : 1; }; static tpm2_shutdown_ctx ctx; static bool on_option(char key, char *value) { UNUSED(value); switch (key) { case 'c': ctx.clear = 1; break; /*no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts [] = { { "clear", no_argument, NULL, 'c' }, }; *opts = tpm2_options_new("c", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); TPM2_SU shutdown_type = ctx.clear ? TPM2_SU_CLEAR : TPM2_SU_STATE; return tpm2_shutdown(context, shutdown_type); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("shutdown", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_sign.c000066400000000000000000000213321412464516500166170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_hash.h" #include "tpm2_options.h" typedef struct tpm_sign_ctx tpm_sign_ctx; struct tpm_sign_ctx { TPMT_TK_HASHCHECK validation; struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } signing_key; TPMI_ALG_HASH halg; TPMI_ALG_SIG_SCHEME sig_scheme; TPMT_SIG_SCHEME in_scheme; TPM2B_DIGEST *digest; char *output_path; BYTE *msg; UINT16 length; char *input_file; tpm2_convert_sig_fmt sig_format; struct { UINT8 d :1; UINT8 t :1; UINT8 o :1; } flags; char *cp_hash_path; char *commit_index; }; static tpm_sign_ctx ctx = { .halg = TPM2_ALG_NULL, .sig_scheme = TPM2_ALG_NULL }; static tool_rc sign_and_save(ESYS_CONTEXT *ectx) { TPMT_SIGNATURE *signature; bool result; if (ctx.cp_hash_path) { TPM2B_DIGEST cp_hash = { .size = 0 }; tool_rc rc = tpm2_sign(ectx, &ctx.signing_key.object, ctx.digest, &ctx.in_scheme, &ctx.validation, &signature, &cp_hash); if (rc != tool_rc_success) { return rc; } bool result = files_save_digest(&cp_hash, ctx.cp_hash_path); if (!result) { rc = tool_rc_general_error; } return rc; } tool_rc rc = tpm2_sign(ectx, &ctx.signing_key.object, ctx.digest, &ctx.in_scheme, &ctx.validation, &signature, NULL); if (rc != tool_rc_success) { goto out; } result = tpm2_convert_sig_save(signature, ctx.sig_format, ctx.output_path); if (!result) { rc = tool_rc_general_error; goto out; } rc = tool_rc_success; out: free(signature); return rc; } static tool_rc init(ESYS_CONTEXT *ectx) { /* * Set signature scheme for key type, or validate chosen scheme is * allowed for key type. */ tool_rc rc = tpm2_alg_util_get_signature_scheme(ectx, ctx.signing_key.object.tr_handle, &ctx.halg, ctx.sig_scheme, &ctx.in_scheme); if (rc != tool_rc_success) { LOG_ERR("Invalid signature scheme for key type!"); return rc; } if (ctx.in_scheme.scheme != TPM2_ALG_ECDAA && ctx.commit_index) { LOG_ERR("Commit counter is only applicable in an ECDAA scheme."); return tool_rc_option_error; } if (ctx.in_scheme.scheme == TPM2_ALG_ECDAA && ctx.commit_index) { bool result = tpm2_util_string_to_uint16(ctx.commit_index, &ctx.in_scheme.details.ecdaa.count); if (!result) { return tool_rc_general_error; } } if (ctx.in_scheme.scheme == TPM2_ALG_ECDAA && ctx.sig_format != signature_format_tss) { LOG_ERR("Only TSS signature format is possible with ECDAA scheme"); return tool_rc_option_error; } if (ctx.cp_hash_path && ctx.output_path) { LOG_ERR("Cannot output signature when calculating cpHash"); return tool_rc_option_error; } if (!ctx.signing_key.ctx_path) { LOG_ERR("Expected option c"); return tool_rc_option_error; } if (!ctx.flags.o && !ctx.cp_hash_path) { LOG_ERR("Expected option o"); return tool_rc_option_error; } if (!ctx.flags.d && ctx.flags.t) { LOG_WARN("Ignoring the specified validation ticket since no TPM " "calculated digest specified."); } /* * Applicable when input data is not a digest, rather the message to sign. * A digest is calculated first in this case. */ if (!ctx.flags.d) { FILE *input = ctx.input_file ? fopen(ctx.input_file, "rb") : stdin; if (!input) { LOG_ERR("Could not open file \"%s\"", ctx.input_file); return tool_rc_general_error; } TPMT_TK_HASHCHECK *temp_validation_ticket; rc = tpm2_hash_file(ectx, ctx.halg, TPM2_RH_OWNER, input, &ctx.digest, &temp_validation_ticket); if (input != stdin) { fclose(input); } if (rc != tool_rc_success) { LOG_ERR("Could not hash input"); } else { ctx.validation = *temp_validation_ticket; } free(temp_validation_ticket); /* * we don't need to perform the digest, just read it */ return rc; } /* * else process it as a pre-computed digest */ ctx.digest = malloc(sizeof(TPM2B_DIGEST)); if (!ctx.digest) { LOG_ERR("oom"); return tool_rc_general_error; } ctx.digest->size = sizeof(ctx.digest->buffer); bool result = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.input_file, &ctx.digest->size, ctx.digest->buffer); if (!result) { return tool_rc_general_error; } /* * Applicable to un-restricted signing keys * NOTE: When digests without tickets are specified for restricted keys, * the sign operation will fail. */ if (ctx.flags.d && !ctx.flags.t) { ctx.validation.tag = TPM2_ST_HASHCHECK; ctx.validation.hierarchy = TPM2_RH_NULL; memset(&ctx.validation.digest, 0, sizeof(ctx.validation.digest)); } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.signing_key.ctx_path = value; break; case 'p': ctx.signing_key.auth_str = value; break; case 'g': ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Could not convert to number or lookup algorithm, got: " "\"%s\"", value); return false; } break; case 's': { ctx.sig_scheme = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.sig_scheme == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } } break; case 'd': ctx.flags.d = 1; break; case 't': { bool result = files_load_validation(value, &ctx.validation); if (!result) { return false; } ctx.flags.t = 1; } break; case 'o': ctx.output_path = value; ctx.flags.o = 1; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.commit_index = value; break; case 'f': ctx.sig_format = tpm2_convert_sig_fmt_from_optarg(value); if (ctx.sig_format == signature_format_err) { return false; } /* no default */ } return true; } static bool on_args(int argc, char *argv[]) { if (argc != 1) { LOG_ERR("Expected one input file, got: %d", argc); return false; } ctx.input_file = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "scheme", required_argument, NULL, 's' }, { "digest", no_argument, NULL, 'd' }, { "signature", required_argument, NULL, 'o' }, { "ticket", required_argument, NULL, 't' }, { "key-context", required_argument, NULL, 'c' }, { "format", required_argument, NULL, 'f' }, { "cphash", required_argument, NULL, 0 }, { "commit-index", required_argument, NULL, 1 }, }; *opts = tpm2_options_new("p:g:dt:o:c:f:s:", ARRAY_LEN(topts), topts, on_option, on_args, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.signing_key.ctx_path, ctx.signing_key.auth_str, &ctx.signing_key.object, false, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { LOG_ERR("Invalid key authorization"); return rc; } rc = init(ectx); if (rc != tool_rc_success) { return rc; } return sign_and_save(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); return tpm2_session_close(&ctx.signing_key.object.session); } static void tpm2_tool_onexit(void) { if (ctx.digest) { free(ctx.digest); } free(ctx.msg); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("sign", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_startauthsession.c000066400000000000000000000241241412464516500213040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_auth_util.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm2_startauthsession_ctx tpm2_startauthsession_ctx; struct tpm2_startauthsession_ctx { struct { TPM2_SE type; TPMI_ALG_HASH halg; struct { /* * Salt generated by esys is encrypted using the tpmkey and * encryption does not require auth to be specified. */ const char *key_context_arg_str; tpm2_loaded_object key_context_object; } tpmkey; struct { /* * While TPM2_CC_StartAuthSession does not required the auth of the * bind to be specified, it is captured here for esys to calculate * the sessionkey. */ const char *bind_context_arg_str; const char *bind_context_auth_str; tpm2_loaded_object bind_context_object; } bind; } session; struct { const char *path; } output; tpm2_session_data *session_data; TPMA_SESSION attrs; bool is_real_policy_session; bool is_hmac_session; bool is_session_encryption_possibly_needed; bool is_session_audit_required; /* Salted/ Bounded session combinations */ bool is_salted; bool is_bounded; bool is_salt_and_bind_obj_same; }; static tpm2_startauthsession_ctx ctx = { .attrs = TPMA_SESSION_CONTINUESESSION, .session = { .type = TPM2_SE_TRIAL, .halg = TPM2_ALG_SHA256 } }; static bool on_option(char key, char *value) { switch (key) { case 0: ctx.is_real_policy_session = true; break; case 1: ctx.is_hmac_session = true; ctx.is_session_audit_required = true; ctx.attrs |= TPMA_SESSION_AUDIT; break; case 'g': ctx.session.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.session.halg == TPM2_ALG_ERROR) { LOG_ERR("Invalid choice for policy digest hash algorithm"); return false; } break; case 'S': ctx.output.path = value; break; case 'c': ctx.is_salt_and_bind_obj_same = true; ctx.session.tpmkey.key_context_arg_str = value; ctx.session.bind.bind_context_arg_str = value; ctx.is_session_encryption_possibly_needed = true; ctx.attrs |= (TPMA_SESSION_DECRYPT | TPMA_SESSION_ENCRYPT); break; case 2: ctx.is_bounded = true; ctx.session.bind.bind_context_arg_str = value; ctx.is_session_encryption_possibly_needed = true; break; case 3: ctx.session.bind.bind_context_auth_str = value; break; case 4: ctx.is_salted = true; ctx.session.tpmkey.key_context_arg_str = value; ctx.is_session_encryption_possibly_needed = true; break; case 5: ctx.is_hmac_session = true; ctx.is_session_encryption_possibly_needed = true; break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "policy-session", no_argument, NULL, 0 }, { "audit-session", no_argument, NULL, 1 }, { "bind-context", required_argument, NULL, 2 }, { "bind-auth", required_argument, NULL, 3 }, { "tpmkey-context", required_argument, NULL, 4 }, { "hmac-session", no_argument, NULL, 5 }, { "hash-algorithm", required_argument, NULL, 'g'}, { "session", required_argument, NULL, 'S'}, { "key-context", required_argument, NULL, 'c'}, }; *opts = tpm2_options_new("g:S:c:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc is_input_options_valid(void) { if (!ctx.output.path) { LOG_ERR("Expected option -S"); return tool_rc_option_error; } /* Trial-session: neither real_policy nor audit/hmac session */ if (!ctx.is_real_policy_session && !ctx.is_hmac_session && ctx.is_session_encryption_possibly_needed) { LOG_ERR("Trial sessions cannot be additionally used as encrypt/decrypt " "session"); return tool_rc_option_error; } /* * Only use --key-context if both bind and tpmkey objects are the same. */ if (ctx.is_salted && ctx.is_salt_and_bind_obj_same) { LOG_ERR("Specify --key-context or tpmkey-context, not both."); return tool_rc_option_error; } if (ctx.is_bounded && ctx.is_salt_and_bind_obj_same) { LOG_ERR("Specify --key-context or --bind-context, not both."); return tool_rc_option_error; } if (ctx.session.bind.bind_context_auth_str && !ctx.session.bind.bind_context_arg_str) { LOG_ERR("Specify the bind entity when specifying the bind auth " "even when bind is same as tpmkey object."); return tool_rc_option_error; } /* * Setting sessions for audit should be handled with tpm2_sessionconfig * The following support is for backwards compatibility */ if (ctx.is_real_policy_session && ctx.is_session_audit_required) { LOG_ERR("Policy sessions cannot be additionally used for audit"); return tool_rc_option_error; } /* * A session cannot be without a purpose. */ if (!(ctx.attrs & TPMA_SESSION_AUDIT) && !(ctx.attrs & TPMA_SESSION_ENCRYPT) && !(ctx.attrs & TPMA_SESSION_DECRYPT) && ctx.is_hmac_session) { LOG_WARN("Session has to be used either for auth and/or audit and/or " "parameter-encryption/decryption. Use session-config tool to " "specify the use"); } return tool_rc_success; } static tool_rc setup_session_data(void) { if (ctx.is_real_policy_session) { ctx.session.type = TPM2_SE_POLICY; } if (ctx.is_hmac_session) { ctx.session.type = TPM2_SE_HMAC; } ctx.session_data = tpm2_session_data_new(ctx.session.type); if (!ctx.session_data) { LOG_ERR("oom"); return tool_rc_general_error; } tpm2_session_set_path(ctx.session_data, ctx.output.path); tpm2_session_set_authhash(ctx.session_data, ctx.session.halg); if (ctx.is_session_encryption_possibly_needed) { TPMT_SYM_DEF sym = { .algorithm = TPM2_ALG_AES, .keyBits = { .aes = 128 }, .mode = { .aes = TPM2_ALG_CFB } }; tpm2_session_set_symmetric(ctx.session_data, &sym); } if (ctx.session.bind.bind_context_arg_str) { tpm2_session_set_bind(ctx.session_data, ctx.session.bind.bind_context_object.tr_handle); } if (ctx.session.tpmkey.key_context_arg_str) { tpm2_session_set_key(ctx.session_data, ctx.session.tpmkey.key_context_object.tr_handle); } tpm2_session_set_attrs(ctx.session_data, ctx.attrs); return tool_rc_success; } static tool_rc process_input_data(ESYS_CONTEXT *ectx) { /* * Backwards compatibility behavior/ side-effect: * * The presence of a tpmkey and bind object should not result in setting up * the session for parameter encryption. It is not a requirement. IOW one * can have a salted and bounded session and not perform parameter * encryption. */ if (ctx.session.tpmkey.key_context_arg_str) { /* * attempt to set up the encryption parameters for this, we load an ESYS_TR * from disk for transient objects and we load from tpm public for * persistent objects. Deserialized ESYS TR objects are checked. */ tool_rc rc = tpm2_util_object_load(ectx, ctx.session.tpmkey.key_context_arg_str, &ctx.session.tpmkey.key_context_object, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } /* if loaded object is non-permanant, it should ideally be persistent */ if (ctx.session.tpmkey.key_context_object.handle) { bool is_transient = (ctx.session.tpmkey.key_context_object.handle >> TPM2_HR_SHIFT) == TPM2_HT_TRANSIENT; if (!is_transient) { LOG_WARN("check public portion of the tpmkey manually"); } } } /* * We need to load the bind object and set its auth value in the bind * objects ESYS_TR. * * A loaded object creates another session and that is not what we want. */ if (ctx.session.bind.bind_context_arg_str) { tool_rc rc = tpm2_util_object_load(ectx, ctx.session.bind.bind_context_arg_str, &ctx.session.bind.bind_context_object, TPM2_HANDLE_ALL_W_NV); if (rc != tool_rc_success) { return rc; } } if (ctx.session.bind.bind_context_auth_str) { TPM2B_AUTH authvalue = { 0 }; bool result = handle_str_password( ctx.session.bind.bind_context_auth_str, &authvalue); if (!result) { return tool_rc_general_error; } tool_rc rc = tpm2_tr_set_auth(ectx, ctx.session.bind.bind_context_object.tr_handle, &authvalue); if (rc != tool_rc_success) { LOG_ERR("Failed setting auth in the bind object ESYS_TR"); return rc; } } return setup_session_data(); } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); //Check input options tool_rc rc = is_input_options_valid(); if (rc != tool_rc_success) { return rc; } //Process inputs rc = process_input_data(ectx); if (rc != tool_rc_success) { return rc; } //ESAPI call to start session tpm2_session *s = NULL; rc = tpm2_session_open(ectx, ctx.session_data, &s); if (rc != tool_rc_success) { return rc; } //Process outputs return tpm2_session_close(&s); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("startauthsession", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_startup.c000066400000000000000000000027101412464516500173600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" /* * Both the Microsoft and IBM TPM2 simulators require some specific setup * before they can be used by the SAPI. This setup is specific to the * simulators and is something that the low-level hardware / firmware does * for a discrete TPM. * NOTE: In the code that interacts with a TPM this can be a very ugly * abstraction leak. */ typedef struct tpm2_startup_ctx tpm2_startup_ctx; struct tpm2_startup_ctx { UINT8 clear :1; }; static tpm2_startup_ctx ctx; static bool on_option(char key, char *value) { UNUSED(value); switch (key) { case 'c': ctx.clear = 1; break; /*no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts [] = { { "clear", no_argument, NULL, 'c' }, }; *opts = tpm2_options_new("c", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); TPM2_SU startup_type = ctx.clear ? TPM2_SU_CLEAR : TPM2_SU_STATE; LOG_INFO("Sending TPM_Startup command with type: %s", ctx.clear ? "TPM2_SU_CLEAR" : "TPM2_SU_STATE"); return tpm2_startup(context, startup_type); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("startup", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_stirrandom.c000066400000000000000000000031571412464516500200460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_options.h" /* Spec enforce input data to be not longer than 128 bytes */ #define MAX_SIZE_TO_READ 128 typedef struct tpm_stirrandom_ctx tpm_stirrandom_ctx; struct tpm_stirrandom_ctx { TPM2B_SENSITIVE_DATA in_data; char *in_file; }; static tpm_stirrandom_ctx ctx = { .in_data = { .size = MAX_SIZE_TO_READ } }; static bool on_args(int argc, char **argv) { if (argc != 1) { LOG_ERR("Only supports one FILE_INPUT file, got %d arguments", argc); return false; } ctx.in_file = argv[0]; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_args, 0); return *opts != NULL; } static bool load_sensitive(void) { bool res = files_load_bytes_from_buffer_or_file_or_stdin(NULL, ctx.in_file, &ctx.in_data.size, ctx.in_data.buffer); if (!res) { LOG_ERR("Error while reading data from file or stdin"); return false; } if (ctx.in_data.size == 0) { LOG_ERR("Data size to send is zero"); return false; } LOG_INFO("Submitting %d bytes to TPM", ctx.in_data.size); return true; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); if (!load_sensitive()) { return tool_rc_general_error; } return tpm2_stirrandom(ectx, &ctx.in_data); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("stirrandom", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_testparms.c000066400000000000000000000062541412464516500177070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "log.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_testparms_ctx tpm_testparms_ctx; struct tpm_testparms_ctx { TPMT_PUBLIC_PARMS inputalg; }; static tpm_testparms_ctx ctx; static tool_rc tpm_testparms(ESYS_CONTEXT *ectx) { TSS2_RC rval = Esys_TestParms(ectx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &(ctx.inputalg)); /* * TODO: this is a good candidate for flatten support via Tss2_RC_Decode(rval); */ if (rval != TSS2_RC_SUCCESS) { if ((rval & (TPM2_RC_P | TPM2_RC_1)) == (TPM2_RC_P | TPM2_RC_1)) { rval &= ~(TPM2_RC_P | TPM2_RC_1); switch (rval) { case TPM2_RC_CURVE: LOG_ERR("Specified elliptic curve is unsupported"); break; case TPM2_RC_HASH: LOG_ERR("Specified hash is unsupported"); break; case TPM2_RC_SCHEME: LOG_ERR("Specified signing scheme is unsupported or " "incompatible"); break; case TPM2_RC_KDF: LOG_ERR("Specified key derivation function is unsupported"); break; case TPM2_RC_MGF: LOG_ERR("Specified mask generation function is unsupported"); break; case TPM2_RC_KEY_SIZE: LOG_ERR("Specified key size is unsupported"); break; case TPM2_RC_SYMMETRIC: LOG_ERR( "Specified symmetric algorithm or key length is " "unsupported"); break; case TPM2_RC_ASYMMETRIC: LOG_ERR("Specified asymmetric algorithm is unsupported"); break; case TPM2_RC_MODE: LOG_ERR("Specified symmetric mode unsupported"); break; case TPM2_RC_VALUE: default: LOG_ERR("Unsupported algorithm specification"); break; } return tool_rc_unsupported; } LOG_PERR(Esys_TestParms, rval); return tool_rc_general_error; } return tool_rc_success; } static bool on_arg(int argc, char **argv) { if (argc < 1) { LOG_ERR("Expected one algorithm specification, got: 0"); return false; } TPM2B_PUBLIC algorithm = { 0 }; if (!tpm2_alg_util_handle_ext_alg(argv[0], &algorithm)) { LOG_ERR("Invalid or unsupported by the tool : %s", argv[0]); return false; } ctx.inputalg.type = algorithm.publicArea.type; memcpy(&ctx.inputalg.parameters, &algorithm.publicArea.parameters, sizeof(TPMU_PUBLIC_PARMS)); return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { *opts = tpm2_options_new(NULL, 0, NULL, NULL, on_arg, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); return tpm_testparms(ectx); } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("testparms", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL) tpm2-tools-5.2/tools/tpm2_tool.c000066400000000000000000000143151412464516500166370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include #include "log.h" #include "tpm2_errata.h" #include "tpm2_options.h" #include "tpm2_tool.h" #include "tpm2_tool_output.h" static void esys_teardown(ESYS_CONTEXT **esys_context) { if (esys_context == NULL) return; if (*esys_context == NULL) return; Esys_Finalize(esys_context); } static void teardown_full(ESYS_CONTEXT **esys_context) { TSS2_TCTI_CONTEXT *tcti_context = NULL; TSS2_RC rc; if (!*esys_context) { return; } rc = Esys_GetTcti(*esys_context, &tcti_context); if (rc != TPM2_RC_SUCCESS) return; esys_teardown(esys_context); Tss2_TctiLdr_Finalize(&tcti_context); } static ESYS_CONTEXT *ctx_init(TSS2_TCTI_CONTEXT *tcti_ctx) { ESYS_CONTEXT *esys_ctx; TSS2_RC rval = Esys_Initialize(&esys_ctx, tcti_ctx, NULL); if (rval != TPM2_RC_SUCCESS) { LOG_PERR(Esys_Initialize, rval); return NULL; } return esys_ctx; } /* * Build a list of the TPM2 tools linked into this executable */ #ifndef TPM2_TOOLS_MAX #define TPM2_TOOLS_MAX 1024 #endif static const tpm2_tool *tools[TPM2_TOOLS_MAX]; static unsigned tool_count; void tpm2_tool_register(const tpm2_tool *tool) { if (tool_count < TPM2_TOOLS_MAX) { tools[tool_count++] = tool; } else { LOG_ERR("Over tool count"); abort(); } } static const char *tpm2_tool_name(const char *arg) { const char *name = rindex(arg, '/'); if (name) { name++; // skip the '/' } else { name = arg; // use the full executable name as is } if (strncmp(name, "tpm2_", 5) == 0) { name += 5; } return name; } static const tpm2_tool *tpm2_tool_lookup(int *argc, char ***argv) { // find the executable name in the path // and skip "tpm2_" prefix if it is present const char *name = tpm2_tool_name((*argv)[0]); // if this was invoked as 'tpm2', then try again with the second argument if (strcmp(name, "tpm2") == 0) { if (--(*argc) == 0) { return NULL; } (*argv)++; name = tpm2_tool_name((*argv)[0]); } // search the tools array for a matching name for(unsigned i = 0 ; i < tool_count ; i++) { const tpm2_tool * const tool = tools[i]; if (!tool || !tool->name) { continue; } if (strcmp(name, tool->name) == 0) { return tool; } } // not found? should print a table of the tools return NULL; } /* * This program is a template for TPM2 tools that use the SAPI. It does * nothing more than parsing command line options that allow the caller to * specify which TCTI to use for the test. */ static struct tool_context { ESYS_CONTEXT *ectx; tpm2_options *tool_opts; } ctx; static void main_onexit(void) { teardown_full(&ctx.ectx); tpm2_options_free(ctx.tool_opts); } int main(int argc, char **argv) { /* get rid of: * owner execute (1) * group execute (1) * other write + read + execute (7) */ umask(0117); if (!strcmp(argv[0], "tpm2")) { if (argc == 1 || (argc == 2 && (!strcmp(argv[1],"--help") || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help=man")))) { char *options[2] = {"tpm2","--help=man"}; tpm2_handle_options(2, options, 0, 0, 0); exit(tool_rc_success); } if ((argc == 2 && (!strcmp(argv[1],"--version") || !strcmp(argv[1], "-v") ))) { tpm2_handle_options(argc, argv, 0, 0, 0); exit(tool_rc_success); } } /* don't buffer stdin/stdout/stderr so pipes work */ setvbuf (stdin, NULL, _IONBF, 0); setvbuf (stdout, NULL, _IONBF, 0); setvbuf (stderr, NULL, _IONBF, 0); const tpm2_tool * const tool = tpm2_tool_lookup(&argc, &argv); if (!tool) { LOG_ERR("%s: unknown tool. Available tpm2 commands:", argv[0]); for(unsigned i = 0 ; i < tool_count ; i++) { fprintf(stderr, "%s\n", tools[i]->name); } exit(tool_rc_general_error); } atexit(main_onexit); tool_rc ret = tool_rc_general_error; if (tool->onstart) { bool res = tool->onstart(&ctx.tool_opts); if (!res) { LOG_ERR("retrieving tool options"); exit(tool_rc_general_error); } } if (tool->onexit) { atexit(tool->onexit); } tpm2_option_flags flags = { .all = 0 }; TSS2_TCTI_CONTEXT *tcti = NULL; tpm2_option_code rc = tpm2_handle_options(argc, argv, ctx.tool_opts, &flags, &tcti); if (rc != tpm2_option_code_continue) { ret = rc == tpm2_option_code_err ? tool_rc_general_error : tool_rc_success; exit(ret); } if (flags.verbose) { log_set_level(log_level_verbose); } /* * We don't want a cyclic dependency between tools/options. Resolving those * works well on linux/elf based systems, but darwin and windows tend to * fall flat on there face. This is why we set quiet mode outside of * option and argument life-cycle. Thus TOOL_OUTPUT is only guaranteed * to respect quiet from here on out (onrun and onexit). */ if (flags.quiet) { tpm2_tool_output_disable(); } if (tcti) { ctx.ectx = ctx_init(tcti); if (!ctx.ectx) { exit(tool_rc_tcti_error); } } if (flags.enable_errata) { tpm2_errata_init(ctx.ectx); } /* * Call the specific tool, all tools implement this function instead of * 'main'. */ ret = tool->onrun(ctx.ectx, flags); if (tool->onstop) { tool_rc tmp_rc = tool->onstop(ctx.ectx); /* if onrun() passed, the error code should come from onstop() */ ret = ret == tool_rc_success ? tmp_rc : ret; } switch (ret) { case tool_rc_success: /* nothing to do here */ break; case tool_rc_option_error: tpm2_print_usage(argv[0], ctx.tool_opts); break; default: LOG_ERR("Unable to run %s", argv[0]); } exit(ret); } tpm2-tools-5.2/tools/tpm2_tool.h000066400000000000000000000037571412464516500166540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #ifndef MAIN_H #define MAIN_H #include #include #include "tool_rc.h" #include "tpm2_options.h" #include "tpm2_tool_output.h" /** * An optional interface for tools to specify what options they support. * They are concatenated with main's options and passed to getopt_long. * @param opts * The callee can choose to set *opts to a tpm_options pointer allocated * via tpm2_options_new(). Setting *opts to NULL is not an error, and * Indicates that no options are specified by the tool. * * @return * True on success, false on error. */ typedef bool (*tpm2_tool_onstart_t)(tpm2_options **opts); /** * This is the main interface for tools, after tcti and sapi/esapi initialization * are performed. * @param ectx * The system/esapi api context. * @param flags * Flags that tools may wish to respect. * @return * A tool_rc indicating status. */ typedef tool_rc (*tpm2_tool_onrun_t)(ESYS_CONTEXT *ectx, tpm2_option_flags flags); /** * Called after tpm2_tool_onrun() is invoked. ESAPI context is still valid during this call. * @param ectx * The system/esapi api context. * @return * A tool_rc indicating status. */ typedef tool_rc (*tpm2_tool_onstop_t)(ESYS_CONTEXT *ectx); /** * Called when the tool is exiting, useful for cleanup. */ typedef void (*tpm2_tool_onexit_t)(void); typedef struct { const char * name; tpm2_tool_onstart_t onstart; tpm2_tool_onrun_t onrun; tpm2_tool_onstop_t onstop; tpm2_tool_onexit_t onexit; } tpm2_tool; void tpm2_tool_register(const tpm2_tool * tool); #define TPM2_TOOL_REGISTER(tool_name,tool_onstart,tool_onrun,tool_onstop,tool_onexit) \ static const tpm2_tool tool = { \ .name = tool_name, \ .onstart = tool_onstart, \ .onrun = tool_onrun, \ .onstop = tool_onstop, \ .onexit = tool_onexit, \ }; \ static void \ __attribute__((__constructor__)) \ __attribute__((__used__)) \ _tpm2_tool_init(void) \ { \ tpm2_tool_register(&tool); \ } #endif /* MAIN_H */ tpm2-tools-5.2/tools/tpm2_unseal.c000066400000000000000000000162741412464516500171570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "tpm2.h" #include "tpm2_tool.h" typedef struct tpm_unseal_ctx tpm_unseal_ctx; #define MAX_SESSIONS 3 #define MAX_AUX_SESSIONS 2 struct tpm_unseal_ctx { /* * Inputs */ struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } sealkey; /* * Outputs */ char *output_file_path; TPM2B_SENSITIVE_DATA *output_data; /* * Parameter hashes */ const char *cp_hash_path; TPM2B_DIGEST cp_hash; const char *rp_hash_path; TPM2B_DIGEST rp_hash; bool is_command_dispatch; TPMI_ALG_HASH parameter_hash_algorithm; /* * Aux sessions */ uint8_t aux_session_cnt; tpm2_session *aux_session[MAX_AUX_SESSIONS]; const char *aux_session_path[MAX_AUX_SESSIONS]; ESYS_TR aux_session_handle[MAX_AUX_SESSIONS]; }; static tpm_unseal_ctx ctx = { .aux_session_handle[0] = ESYS_TR_NONE, .aux_session_handle[1] = ESYS_TR_NONE, .parameter_hash_algorithm = TPM2_ALG_ERROR, }; tool_rc unseal(ESYS_CONTEXT *ectx) { /* * 1. TPM2_CC_ OR Retrieve cpHash */ return tpm2_unseal(ectx, &ctx.sealkey.object, &ctx.output_data, &ctx.cp_hash, &ctx.rp_hash, ctx.parameter_hash_algorithm, ctx.aux_session_handle[0], ctx.aux_session_handle[1]); } static tool_rc process_output(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Outputs that do not require TPM2_CC_ dispatch */ bool is_file_op_success = true; if (ctx.cp_hash_path) { is_file_op_success = files_save_digest(&ctx.cp_hash, ctx.cp_hash_path); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.is_command_dispatch) { return tool_rc_success; } /* * 2. Outputs generated after TPM2_CC_ dispatch */ if (ctx.output_file_path) { is_file_op_success = files_save_bytes_to_file(ctx.output_file_path, ctx.output_data->buffer, ctx.output_data->size); if (!is_file_op_success) { return tool_rc_general_error; } } if (!ctx.output_file_path) { is_file_op_success = files_write_bytes(stdout, ctx.output_data->buffer, ctx.output_data->size); if (!is_file_op_success) { return tool_rc_general_error; } } if (ctx.rp_hash_path) { is_file_op_success = files_save_digest(&ctx.rp_hash, ctx.rp_hash_path); } return is_file_op_success ? tool_rc_success : tool_rc_general_error; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { /* * 1. Object and auth initializations */ /* * 1.a Add the new-auth values to be set for the object. */ /* * 1.b Add object names and their auth sessions */ tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.sealkey.ctx_path, ctx.sealkey.auth_str, &ctx.sealkey.object, false, TPM2_HANDLES_FLAGS_TRANSIENT | TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { LOG_ERR("Invalid item handle authorization"); return rc; } /* * 2. Restore auxiliary sessions */ rc = tpm2_util_aux_sessions_setup(ectx, ctx.aux_session_cnt, ctx.aux_session_path, ctx.aux_session_handle, ctx.aux_session); if (rc != tool_rc_success) { return rc; } /* * 3. Command specific initializations dependent on loaded objects */ /* * 4. Configuration for calculating the pHash */ /* 4.a Determine pHash length and alg */ tpm2_session *all_sessions[MAX_SESSIONS] = { ctx.sealkey.object.session, ctx.aux_session[0], ctx.aux_session[1] }; const char **cphash_path = ctx.cp_hash_path ? &ctx.cp_hash_path : 0; const char **rphash_path = ctx.rp_hash_path ? &ctx.rp_hash_path : 0; ctx.parameter_hash_algorithm = tpm2_util_calculate_phash_algorithm(ectx, cphash_path, &ctx.cp_hash, rphash_path, &ctx.rp_hash, all_sessions); /* * 4.b Determine if TPM2_CC_ is to be dispatched * !rphash && !cphash [Y] * !rphash && cphash [N] * rphash && !cphash [Y] * rphash && cphash [Y] */ ctx.is_command_dispatch = (ctx.cp_hash_path && !ctx.rp_hash_path) ? false : true; return rc; } static tool_rc check_options(void) { if (!ctx.sealkey.ctx_path) { LOG_ERR("Expected option c"); return tool_rc_option_error; } return tool_rc_success; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.sealkey.ctx_path = value; break; case 'p': { ctx.sealkey.auth_str = value; } break; case 'o': ctx.output_file_path = value; break; case 0: ctx.cp_hash_path = value; break; case 1: ctx.rp_hash_path = value; break; case 'S': ctx.aux_session_path[ctx.aux_session_cnt] = value; if (ctx.aux_session_cnt < MAX_AUX_SESSIONS) { ctx.aux_session_cnt++; } else { return false; } break; } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static const struct option topts[] = { { "auth", required_argument, NULL, 'p' }, { "output", required_argument, NULL, 'o' }, { "object-context", required_argument, NULL, 'c' }, { "cphash", required_argument, NULL, 0 }, { "rphash", required_argument, NULL, 1 }, { "session", required_argument, NULL, 'S' }, }; *opts = tpm2_options_new("S:p:o:c:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); /* * 1. Process options */ tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } /* * 2. Process inputs */ rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } /* * 3. TPM2_CC_ call */ rc = unseal(ectx); if (rc != tool_rc_success) { return rc; } /* * 4. Process outputs */ return process_output(ectx); } static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { UNUSED(ectx); /* * 1. Free objects */ free(ctx.output_data); /* * 2. Close authorization sessions */ tool_rc rc = tool_rc_success; tool_rc tmp_rc = tool_rc_success; if (!ctx.cp_hash_path) { tmp_rc = tpm2_session_close(&ctx.sealkey.object.session); if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } /* * 3. Close auxiliary sessions */ uint8_t i = 0; for(i = 0; i < ctx.aux_session_cnt; i++) { if (ctx.aux_session_path[i]) { tmp_rc = tpm2_session_close(&ctx.aux_session[i]); } if (tmp_rc != tool_rc_success) { rc = tmp_rc; } } return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("unseal", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL) tpm2-tools-5.2/tools/tpm2_verifysignature.c000066400000000000000000000164121412464516500211100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_alg_util.h" #include "tpm2_convert.h" #include "tpm2_hash.h" #include "tpm2_options.h" typedef struct tpm2_verifysig_ctx tpm2_verifysig_ctx; struct tpm2_verifysig_ctx { union { struct { UINT8 digest :1; UINT8 halg :1; UINT8 msg :1; UINT8 sig :1; UINT8 ticket :1; UINT8 key_context :1; UINT8 fmt; }; UINT8 all; } flags; TPMI_ALG_SIG_SCHEME format; TPMI_ALG_HASH halg; TPM2B_DIGEST *msg_hash; TPMT_SIGNATURE signature; char *msg_file_path; char *sig_file_path; char *out_file_path; const char *context_arg; tpm2_loaded_object key_context_object; }; static tpm2_verifysig_ctx ctx = { .format = TPM2_ALG_ERROR, .msg_hash = NULL, .halg = TPM2_ALG_SHA256 }; static tool_rc verify_signature(ESYS_CONTEXT *context) { TPMT_TK_VERIFIED *validation = NULL; tool_rc rc = tpm2_verifysignature(context, ctx.key_context_object.tr_handle, ctx.msg_hash, &ctx.signature, &validation); if (rc != tool_rc_success) { goto out; } /* * NULL Hierarchies don't produce validation data, so let the user know * by issuing a warning. */ if (ctx.out_file_path) { if (validation->hierarchy == TPM2_RH_NULL) { LOG_WARN("The NULL hierarchy doesn't produce a validation ticket," " not outputting ticket"); } else { if (!files_save_ticket(validation, ctx.out_file_path)) { rc = tool_rc_general_error; } } } out: free(validation); return rc; } static TPM2B *message_from_file(const char *msg_file_path) { unsigned long size; bool result = files_get_file_size_path(msg_file_path, &size); if (!result) { return NULL; } if (!size) { LOG_ERR("The msg file \"%s\" is empty", msg_file_path); return NULL; } TPM2B *msg = (TPM2B *) calloc(1, sizeof(TPM2B) + size); if (!msg) { LOG_ERR("OOM"); return NULL; } UINT16 tmp = msg->size = size; if (!files_load_bytes_from_path(msg_file_path, msg->buffer, &tmp)) { free(msg); return NULL; } return msg; } static tool_rc init(ESYS_CONTEXT *context) { tool_rc rc = tool_rc_general_error; /* check flags for mismatches */ if (ctx.flags.digest && (ctx.flags.msg || ctx.flags.halg)) { LOG_ERR("Cannot specify --digest (-d) and ( --msg (-m) or --halg (-g) )"); return tool_rc_option_error; } if (!(ctx.context_arg && ctx.flags.sig)) { LOG_ERR("--key-context (-c) and --sig (-s) are required"); return tool_rc_option_error; } TPM2B *msg = NULL; tool_rc tmp_rc = tpm2_util_object_load(context, ctx.context_arg, &ctx.key_context_object, TPM2_HANDLE_ALL_W_NV); if (tmp_rc != tool_rc_success) { return tmp_rc; } if (ctx.flags.msg) { msg = message_from_file(ctx.msg_file_path); if (!msg) { /* message_from_file() logs specific error no need to here */ return tool_rc_general_error; } } if (ctx.flags.sig) { tpm2_convert_sig_fmt fmt = ctx.flags.fmt ? signature_format_plain : signature_format_tss; bool res = tpm2_convert_sig_load(ctx.sig_file_path, fmt, ctx.format, ctx.halg, &ctx.signature); if (!res) { goto err; } } /* If no digest is specified, compute it */ if (!ctx.flags.digest) { if (!msg) { /* * This is a redundant check since main() checks this case, but * we'll add it here to silence any complainers (such as static * analysers). */ LOG_ERR("No digest set and no message file to compute from, cannot " "compute message hash!"); goto err; } tmp_rc = tpm2_hash_compute_data(context, ctx.halg, TPM2_RH_NULL, msg->buffer, msg->size, &ctx.msg_hash, NULL); if (tmp_rc != tool_rc_success) { rc = tmp_rc; LOG_ERR("Compute message hash failed!"); goto err; } } rc = tool_rc_success; err: free(msg); return rc; } static bool on_option(char key, char *value) { switch (key) { case 'c': ctx.context_arg = value; break; case 'g': { ctx.halg = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_hash); if (ctx.halg == TPM2_ALG_ERROR) { LOG_ERR("Unable to convert algorithm, got: \"%s\"", value); return false; } ctx.flags.halg = 1; } break; case 'm': { ctx.msg_file_path = value; ctx.flags.msg = 1; } break; case 'd': { ctx.msg_hash = malloc(sizeof(TPM2B_DIGEST)); ctx.msg_hash->size = sizeof(ctx.msg_hash->buffer); if (!files_load_bytes_from_path(value, ctx.msg_hash->buffer, &ctx.msg_hash->size)) { LOG_ERR("Could not load digest from file!"); return false; } ctx.flags.digest = 1; } break; case 0: LOG_WARN("Option \"--format\" is deprecated, use \"--scheme\""); /* falls through */ case 'f': ctx.format = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); if (ctx.format == TPM2_ALG_ERROR) { LOG_ERR("Unknown signing scheme, got: \"%s\"", value); return false; } ctx.flags.fmt = 1; break; case 's': ctx.sig_file_path = value; ctx.flags.sig = 1; break; case 't': ctx.out_file_path = value; ctx.flags.ticket = 1; break; /* no default */ } return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { const struct option topts[] = { { "digest", required_argument, NULL, 'd' }, { "hash-algorithm", required_argument, NULL, 'g' }, { "message", required_argument, NULL, 'm' }, { "format", required_argument, NULL, 0 }, { "scheme", required_argument, NULL, 'f' }, { "signature", required_argument, NULL, 's' }, { "ticket", required_argument, NULL, 't' }, { "key-context", required_argument, NULL, 'c' }, }; *opts = tpm2_options_new("g:m:d:f:s:t:c:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *context, tpm2_option_flags flags) { UNUSED(flags); /* initialize and process */ tool_rc rc = init(context); if (rc != tool_rc_success) { return rc; } rc = verify_signature(context); if (rc != tool_rc_success) { LOG_ERR("Verify signature failed!"); return rc; } return tool_rc_success; } static void tpm2_tool_onexit(void) { if (ctx.msg_hash) { free(ctx.msg_hash); } } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("verifysignature", tpm2_tool_onstart, tpm2_tool_onrun, NULL, tpm2_tool_onexit) tpm2-tools-5.2/tools/tpm2_zgen2phase.c000066400000000000000000000126421412464516500177310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ #include "files.h" #include "log.h" #include "object.h" #include "tpm2.h" #include "tpm2_tool.h" #include "tpm2_auth_util.h" #include "tpm2_alg_util.h" #include "tpm2_options.h" typedef struct tpm_ecdhzgen_ctx tpm_ecdhzgen_ctx; struct tpm_ecdhzgen_ctx { struct { const char *ctx_path; const char *auth_str; tpm2_loaded_object object; } ecc_key; const char *output_z1_path; const char *output_z2_path; TPM2B_ECC_POINT *Z1; TPM2B_ECC_POINT *Z2; const char *static_public_path; const char *ephemeral_public_path; TPM2B_ECC_POINT Q1; TPM2B_ECC_POINT Q2; UINT16 commit_counter; TPMI_ECC_KEY_EXCHANGE keyexchange_scheme; }; static tpm_ecdhzgen_ctx ctx = { .keyexchange_scheme = TPM2_ALG_ECDH, }; static bool on_option(char key, char *value) { bool result = true; switch (key) { case 'c': ctx.ecc_key.ctx_path = value; break; case 'p': ctx.ecc_key.auth_str = value; break; case 's': ctx.keyexchange_scheme = tpm2_alg_util_from_optarg(value, tpm2_alg_util_flags_sig); break; case 't': result = tpm2_util_string_to_uint16(value, &ctx.commit_counter); if (!result) { LOG_ERR("Could not convert commit counter to number, got: \"%s\"", value); return false; } break; case 0: ctx.static_public_path = value; break; case 1: ctx.ephemeral_public_path = value; break; case 2: ctx.output_z1_path = value; break; case 3: ctx.output_z2_path = value; break; }; return true; } static bool tpm2_tool_onstart(tpm2_options **opts) { static struct option topts[] = { { "key-context", required_argument, NULL, 'c' }, { "key-auth", required_argument, NULL, 'p' }, { "scheme", required_argument, NULL, 's' }, { "counter", required_argument, NULL, 't' }, { "static-public", required_argument, NULL, 0 }, { "ephemeral-public", required_argument, NULL, 1 }, { "output-Z1", required_argument, NULL, 2 }, { "output-Z2", required_argument, NULL, 3 }, }; *opts = tpm2_options_new("c:p:s:t:", ARRAY_LEN(topts), topts, on_option, NULL, 0); return *opts != NULL; } static tool_rc check_options(void) { if (ctx.keyexchange_scheme != TPM2_ALG_ECDH && ctx.keyexchange_scheme != TPM2_ALG_ECMQV && ctx.keyexchange_scheme != TPM2_ALG_SM2) { LOG_ERR("Unknown signing scheme"); return tool_rc_general_error; } if (!ctx.ecc_key.ctx_path) { LOG_ERR("Specify an ecc key handle for context"); return tool_rc_option_error; } if (!ctx.static_public_path) { LOG_ERR("Specify path to read the static public data from."); return tool_rc_option_error; } if (!ctx.ephemeral_public_path) { LOG_ERR("Specify path to read the ephemeral public data from."); return tool_rc_option_error; } if (!ctx.output_z1_path) { LOG_ERR("Specify path to save the Z1 data."); return tool_rc_option_error; } if (!ctx.output_z2_path) { LOG_ERR("Specify path to save the Z2 data."); return tool_rc_option_error; } return tool_rc_success; } static tool_rc process_inputs(ESYS_CONTEXT *ectx) { tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.ecc_key.ctx_path, ctx.ecc_key.auth_str, &ctx.ecc_key.object, false, TPM2_HANDLES_FLAGS_TRANSIENT|TPM2_HANDLES_FLAGS_PERSISTENT); if (rc != tool_rc_success) { return rc; } bool result = true; result = files_load_ecc_point(ctx.static_public_path, &ctx.Q1); if (!result) { LOG_ERR("Failed to load static public input ECC point Q1"); return tool_rc_general_error; } result = files_load_ecc_point(ctx.ephemeral_public_path, &ctx.Q2); if (!result) { LOG_ERR("Failed to load static public input ECC point Q2"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc process_outputs(void) { bool result = files_save_ecc_point(ctx.Z1, ctx.output_z1_path); if (!result) { LOG_ERR("Failed to write out the ECC point Z1"); return tool_rc_general_error; } result = files_save_ecc_point(ctx.Z2, ctx.output_z2_path); if (!result) { LOG_ERR("Failed to write out the ECC point Z2"); return tool_rc_general_error; } return tool_rc_success; } static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { UNUSED(flags); // Check input options and arguments tool_rc rc = check_options(); if (rc != tool_rc_success) { return rc; } // Process inputs rc = process_inputs(ectx); if (rc != tool_rc_success) { return rc; } // ESAPI call rc = tpm2_zgen2phase(ectx, &ctx.ecc_key.object, &ctx.Q1, &ctx.Q2, &ctx.Z1, &ctx.Z2, ctx.keyexchange_scheme, ctx.commit_counter); if (rc != tool_rc_success) { return rc; } // Process ouputs rc = process_outputs(); return rc; } // Register this tool with tpm2_tool.c TPM2_TOOL_REGISTER("zgen2phase", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL)